linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core
@ 2020-03-02 18:07 Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name Tudor.Ambarus
                   ` (23 more replies)
  0 siblings, 24 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Tudor Ambarus <tudor.ambarus@microchip.com>

Hello,

This patch series is an attempt at getting all manufacturer specific
quirks/code out of the core to make the core logic more readable and
thus ease maintainance.

This is a respin of the last chunk of Boris's work from
https://patchwork.ozlabs.org/cover/1009290/.

Tested an erase-write-read-compare with a 1MB file on the following
flashes: mx25l25635e, w25q128, n25q256a, is25lp256, s25fl256s0,
gd25q256.

Boris Brezillon (21):
  mtd: spi-nor: Stop prefixing generic functions with a manufacturer
    name
  mtd: spi-nor: Prepare core / manufacturer code split
  mtd: spi-nor: Expose stuctures and functions to manufacturer drivers
  mtd: spi-nor: Add the concept of SPI NOR manufacturer driver
  mtd: spi-nor: Move Atmel bits out of core.c
  mtd: spi-nor: Move Eon bits out of core.c
  mtd: spi-nor: Move ESMT bits out of core.c
  mtd: spi-nor: Move Everspin bits out of core.c
  mtd: spi-nor: Move Fujitsu bits out of core.c
  mtd: spi-nor: Move GigaDevice bits out of core.c
  mtd: spi-nor: Move Intel bits out of core.c
  mtd: spi-nor: Move ISSI bits out of core.c
  mtd: spi-nor: Move Macronix bits out of core.c
  mtd: spi-nor: Move Micron/ST bits out of core.c
  mtd: spi-nor: Move Spansion bits out of core.c
  mtd: spi-nor: Move SST bits out of core.c
  mtd: spi-nor: Move Winbond bits out of core.c
  mtd: spi-nor: Move Catalyst bits out of core.c
  mtd: spi-nor: Move Xilinx bits out of core.c
  mtd: spi-nor: Move XMC bits out of core.c
  mtd: spi-nor: Get rid of the now empty spi_nor_ids[] table

Tudor Ambarus (2):
  mtd: spi-nor: Move SFDP logic out of the core
  mtd: spi-nor: Trim what is exposed in spi-nor.h

 drivers/mtd/spi-nor/Kconfig                   |   83 +-
 drivers/mtd/spi-nor/Makefile                  |   26 +-
 drivers/mtd/spi-nor/atmel.c                   |   46 +
 drivers/mtd/spi-nor/catalyst.c                |   29 +
 drivers/mtd/spi-nor/controllers/Kconfig       |   83 +
 drivers/mtd/spi-nor/controllers/Makefile      |    9 +
 .../spi-nor/{ => controllers}/aspeed-smc.c    |    0
 .../{ => controllers}/cadence-quadspi.c       |    0
 .../mtd/spi-nor/{ => controllers}/hisi-sfc.c  |    0
 .../spi-nor/{ => controllers}/intel-spi-pci.c |    0
 .../{ => controllers}/intel-spi-platform.c    |    0
 .../mtd/spi-nor/{ => controllers}/intel-spi.c |    0
 .../mtd/spi-nor/{ => controllers}/intel-spi.h |    0
 .../spi-nor/{ => controllers}/mtk-quadspi.c   |    0
 .../mtd/spi-nor/{ => controllers}/nxp-spifi.c |    0
 drivers/mtd/spi-nor/{spi-nor.c => core.c}     | 2503 ++---------------
 drivers/mtd/spi-nor/core.h                    |  432 +++
 drivers/mtd/spi-nor/eon.c                     |   34 +
 drivers/mtd/spi-nor/esmt.c                    |   25 +
 drivers/mtd/spi-nor/everspin.c                |   27 +
 drivers/mtd/spi-nor/fujitsu.c                 |   20 +
 drivers/mtd/spi-nor/gigadevice.c              |   59 +
 drivers/mtd/spi-nor/intel.c                   |   32 +
 drivers/mtd/spi-nor/issi.c                    |   83 +
 drivers/mtd/spi-nor/macronix.c                |   98 +
 drivers/mtd/spi-nor/micron-st.c               |  129 +
 drivers/mtd/spi-nor/sfdp.c                    | 1206 ++++++++
 drivers/mtd/spi-nor/sfdp.h                    |   98 +
 drivers/mtd/spi-nor/spansion.c                |   95 +
 drivers/mtd/spi-nor/sst.c                     |  151 +
 drivers/mtd/spi-nor/winbond.c                 |  113 +
 drivers/mtd/spi-nor/xilinx.c                  |   94 +
 drivers/mtd/spi-nor/xmc.c                     |   23 +
 include/linux/mtd/spi-nor.h                   |  257 +-
 34 files changed, 3121 insertions(+), 2634 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/atmel.c
 create mode 100644 drivers/mtd/spi-nor/catalyst.c
 create mode 100644 drivers/mtd/spi-nor/controllers/Kconfig
 create mode 100644 drivers/mtd/spi-nor/controllers/Makefile
 rename drivers/mtd/spi-nor/{ => controllers}/aspeed-smc.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/cadence-quadspi.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/hisi-sfc.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/intel-spi-pci.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/intel-spi-platform.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/intel-spi.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/intel-spi.h (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/mtk-quadspi.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/nxp-spifi.c (100%)
 rename drivers/mtd/spi-nor/{spi-nor.c => core.c} (52%)
 create mode 100644 drivers/mtd/spi-nor/core.h
 create mode 100644 drivers/mtd/spi-nor/eon.c
 create mode 100644 drivers/mtd/spi-nor/esmt.c
 create mode 100644 drivers/mtd/spi-nor/everspin.c
 create mode 100644 drivers/mtd/spi-nor/fujitsu.c
 create mode 100644 drivers/mtd/spi-nor/gigadevice.c
 create mode 100644 drivers/mtd/spi-nor/intel.c
 create mode 100644 drivers/mtd/spi-nor/issi.c
 create mode 100644 drivers/mtd/spi-nor/macronix.c
 create mode 100644 drivers/mtd/spi-nor/micron-st.c
 create mode 100644 drivers/mtd/spi-nor/sfdp.c
 create mode 100644 drivers/mtd/spi-nor/sfdp.h
 create mode 100644 drivers/mtd/spi-nor/spansion.c
 create mode 100644 drivers/mtd/spi-nor/sst.c
 create mode 100644 drivers/mtd/spi-nor/winbond.c
 create mode 100644 drivers/mtd/spi-nor/xilinx.c
 create mode 100644 drivers/mtd/spi-nor/xmc.c

-- 
2.23.0

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

* [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-13  6:04   ` Vignesh Raghavendra
  2020-03-02 18:07 ` [PATCH 02/23] mtd: spi-nor: Prepare core / manufacturer code split Tudor.Ambarus
                   ` (22 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Replace the manufacturer prefix by something describing more precisely
what those functions do.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
[tudor.ambarus@microchip.com: prepend spi_nor_ to all modified methods.]
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/spi-nor.c | 88 ++++++++++++++++++-----------------
 1 file changed, 45 insertions(+), 43 deletions(-)

diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
index caf0c109cca0..b15e262765e1 100644
--- a/drivers/mtd/spi-nor/spi-nor.c
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -568,14 +568,15 @@ static int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
 }
 
 /**
- * macronix_set_4byte() - Set 4-byte address mode for Macronix flashes.
+ * spi_nor_en4_ex4_set_4byte() - Enter/Exit 4-byte mode for Macronix like
+ * flashes.
  * @nor:	pointer to 'struct spi_nor'.
  * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
  *		address mode.
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int macronix_set_4byte(struct spi_nor *nor, bool enable)
+static int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable)
 {
 	int ret;
 
@@ -604,14 +605,15 @@ static int macronix_set_4byte(struct spi_nor *nor, bool enable)
 }
 
 /**
- * st_micron_set_4byte() - Set 4-byte address mode for ST and Micron flashes.
+ * spi_nor_en4_ex4_wen_set_4byte() - Set 4-byte address mode for ST and Micron
+ * flashes.
  * @nor:	pointer to 'struct spi_nor'.
  * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
  *		address mode.
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int st_micron_set_4byte(struct spi_nor *nor, bool enable)
+static int spi_nor_en4_ex4_wen_set_4byte(struct spi_nor *nor, bool enable)
 {
 	int ret;
 
@@ -619,7 +621,7 @@ static int st_micron_set_4byte(struct spi_nor *nor, bool enable)
 	if (ret)
 		return ret;
 
-	ret = macronix_set_4byte(nor, enable);
+	ret = spi_nor_en4_ex4_set_4byte(nor, enable);
 	if (ret)
 		return ret;
 
@@ -703,7 +705,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable)
 {
 	int ret;
 
-	ret = macronix_set_4byte(nor, enable);
+	ret = spi_nor_en4_ex4_set_4byte(nor, enable);
 	if (ret || enable)
 		return ret;
 
@@ -755,13 +757,13 @@ static int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr)
 }
 
 /**
- * s3an_sr_ready() - Query the Status Register of the S3AN flash to see if the
- * flash is ready for new commands.
+ * spi_nor_xsr_ready() - Query the Status Register of the S3AN flash to see if
+ * the flash is ready for new commands.
  * @nor:	pointer to 'struct spi_nor'.
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int s3an_sr_ready(struct spi_nor *nor)
+static int spi_nor_xsr_ready(struct spi_nor *nor)
 {
 	int ret;
 
@@ -892,7 +894,7 @@ static int spi_nor_ready(struct spi_nor *nor)
 	int sr, fsr;
 
 	if (nor->flags & SNOR_F_READY_XSR_RDY)
-		sr = s3an_sr_ready(nor);
+		sr = spi_nor_xsr_ready(nor);
 	else
 		sr = spi_nor_sr_ready(nor);
 	if (sr < 0)
@@ -1784,8 +1786,8 @@ static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
 	return ret;
 }
 
-static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
-				 uint64_t *len)
+static void spi_nor_get_locked_range_sr(struct spi_nor *nor, u8 sr, loff_t *ofs,
+					uint64_t *len)
 {
 	struct mtd_info *mtd = &nor->mtd;
 	u8 mask = SR_BP2 | SR_BP1 | SR_BP0;
@@ -1813,8 +1815,8 @@ static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
  * Return 1 if the entire region is locked (if @locked is true) or unlocked (if
  * @locked is false); 0 otherwise
  */
-static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
-				    u8 sr, bool locked)
+static int spi_nor_check_lock_status_sr(struct spi_nor *nor, loff_t ofs,
+					uint64_t len, u8 sr, bool locked)
 {
 	loff_t lock_offs;
 	uint64_t lock_len;
@@ -1822,7 +1824,7 @@ static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, uint64_t le
 	if (!len)
 		return 1;
 
-	stm_get_locked_range(nor, sr, &lock_offs, &lock_len);
+	spi_nor_get_locked_range_sr(nor, sr, &lock_offs, &lock_len);
 
 	if (locked)
 		/* Requested range is a sub-range of locked range */
@@ -1832,16 +1834,16 @@ static int stm_check_lock_status_sr(struct spi_nor *nor, loff_t ofs, uint64_t le
 		return (ofs >= lock_offs + lock_len) || (ofs + len <= lock_offs);
 }
 
-static int stm_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
-			    u8 sr)
+static int spi_nor_is_locked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
+				u8 sr)
 {
-	return stm_check_lock_status_sr(nor, ofs, len, sr, true);
+	return spi_nor_check_lock_status_sr(nor, ofs, len, sr, true);
 }
 
-static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
-			      u8 sr)
+static int spi_nor_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
+				  u8 sr)
 {
-	return stm_check_lock_status_sr(nor, ofs, len, sr, false);
+	return spi_nor_check_lock_status_sr(nor, ofs, len, sr, false);
 }
 
 /*
@@ -1876,7 +1878,7 @@ static int stm_is_unlocked_sr(struct spi_nor *nor, loff_t ofs, uint64_t len,
  *
  * Returns negative on errors, 0 on success.
  */
-static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+static int spi_nor_sr_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *mtd = &nor->mtd;
 	int ret, status_old, status_new;
@@ -1894,16 +1896,16 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 	status_old = nor->bouncebuf[0];
 
 	/* If nothing in our range is unlocked, we don't need to do anything */
-	if (stm_is_locked_sr(nor, ofs, len, status_old))
+	if (spi_nor_is_locked_sr(nor, ofs, len, status_old))
 		return 0;
 
 	/* If anything below us is unlocked, we can't use 'bottom' protection */
-	if (!stm_is_locked_sr(nor, 0, ofs, status_old))
+	if (!spi_nor_is_locked_sr(nor, 0, ofs, status_old))
 		can_be_bottom = false;
 
 	/* If anything above us is unlocked, we can't use 'top' protection */
-	if (!stm_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len),
-				status_old))
+	if (!spi_nor_is_locked_sr(nor, ofs + len, mtd->size - (ofs + len),
+				  status_old))
 		can_be_top = false;
 
 	if (!can_be_bottom && !can_be_top)
@@ -1958,11 +1960,11 @@ static int stm_lock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 }
 
 /*
- * Unlock a region of the flash. See stm_lock() for more info
+ * Unlock a region of the flash. See spi_nor_sr_lock() for more info
  *
  * Returns negative on errors, 0 on success.
  */
-static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
+static int spi_nor_sr_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 {
 	struct mtd_info *mtd = &nor->mtd;
 	int ret, status_old, status_new;
@@ -1980,16 +1982,16 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 	status_old = nor->bouncebuf[0];
 
 	/* If nothing in our range is locked, we don't need to do anything */
-	if (stm_is_unlocked_sr(nor, ofs, len, status_old))
+	if (spi_nor_is_unlocked_sr(nor, ofs, len, status_old))
 		return 0;
 
 	/* If anything below us is locked, we can't use 'top' protection */
-	if (!stm_is_unlocked_sr(nor, 0, ofs, status_old))
+	if (!spi_nor_is_unlocked_sr(nor, 0, ofs, status_old))
 		can_be_top = false;
 
 	/* If anything above us is locked, we can't use 'bottom' protection */
-	if (!stm_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len),
-				status_old))
+	if (!spi_nor_is_unlocked_sr(nor, ofs + len, mtd->size - (ofs + len),
+				    status_old))
 		can_be_bottom = false;
 
 	if (!can_be_bottom && !can_be_top)
@@ -2046,13 +2048,13 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
 }
 
 /*
- * Check if a region of the flash is (completely) locked. See stm_lock() for
- * more info.
+ * Check if a region of the flash is (completely) locked. See spi_nor_sr_lock()
+ * for more info.
  *
  * Returns 1 if entire region is locked, 0 if any portion is unlocked, and
  * negative on errors.
  */
-static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
+static int spi_nor_sr_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
 {
 	int ret;
 
@@ -2060,13 +2062,13 @@ static int stm_is_locked(struct spi_nor *nor, loff_t ofs, uint64_t len)
 	if (ret)
 		return ret;
 
-	return stm_is_locked_sr(nor, ofs, len, nor->bouncebuf[0]);
+	return spi_nor_is_locked_sr(nor, ofs, len, nor->bouncebuf[0]);
 }
 
-static const struct spi_nor_locking_ops stm_locking_ops = {
-	.lock = stm_lock,
-	.unlock = stm_unlock,
-	.is_locked = stm_is_locked,
+static const struct spi_nor_locking_ops spi_nor_sr_locking_ops = {
+	.lock = spi_nor_sr_lock,
+	.unlock = spi_nor_sr_unlock,
+	.is_locked = spi_nor_sr_is_locked,
 };
 
 static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
@@ -4655,7 +4657,7 @@ static void issi_set_default_init(struct spi_nor *nor)
 static void macronix_set_default_init(struct spi_nor *nor)
 {
 	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
-	nor->params.set_4byte = macronix_set_4byte;
+	nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
 }
 
 static void sst_set_default_init(struct spi_nor *nor)
@@ -4668,7 +4670,7 @@ static void st_micron_set_default_init(struct spi_nor *nor)
 	nor->flags |= SNOR_F_HAS_LOCK;
 	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
 	nor->params.quad_enable = NULL;
-	nor->params.set_4byte = st_micron_set_4byte;
+	nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
 }
 
 static void winbond_set_default_init(struct spi_nor *nor)
@@ -4895,7 +4897,7 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
 	 * the default ones.
 	 */
 	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops)
-		nor->params.locking_ops = &stm_locking_ops;
+		nor->params.locking_ops = &spi_nor_sr_locking_ops;
 }
 
 /**
-- 
2.23.0

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

* [PATCH 02/23] mtd: spi-nor: Prepare core / manufacturer code split
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-13  6:08   ` Vignesh Raghavendra
  2020-03-02 18:07 ` [PATCH 03/23] mtd: spi-nor: Move SFDP logic out of the core Tudor.Ambarus
                   ` (21 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Move all SPI NOR controller drivers to a controllers/ sub-directory
so that we only have SPI NOR related source files under
drivers/mtd/spi-nor/.

Rename spi-nor.c into core.c, we are about to split this file in multiple
source files (one per manufacturer, plus one for the SFDP parsing logic).

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Kconfig                   | 83 +------------------
 drivers/mtd/spi-nor/Makefile                  | 10 +--
 drivers/mtd/spi-nor/controllers/Kconfig       | 83 +++++++++++++++++++
 drivers/mtd/spi-nor/controllers/Makefile      |  9 ++
 .../spi-nor/{ => controllers}/aspeed-smc.c    |  0
 .../{ => controllers}/cadence-quadspi.c       |  0
 .../mtd/spi-nor/{ => controllers}/hisi-sfc.c  |  0
 .../spi-nor/{ => controllers}/intel-spi-pci.c |  0
 .../{ => controllers}/intel-spi-platform.c    |  0
 .../mtd/spi-nor/{ => controllers}/intel-spi.c |  0
 .../mtd/spi-nor/{ => controllers}/intel-spi.h |  0
 .../spi-nor/{ => controllers}/mtk-quadspi.c   |  0
 .../mtd/spi-nor/{ => controllers}/nxp-spifi.c |  0
 drivers/mtd/spi-nor/{spi-nor.c => core.c}     |  0
 14 files changed, 95 insertions(+), 90 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/controllers/Kconfig
 create mode 100644 drivers/mtd/spi-nor/controllers/Makefile
 rename drivers/mtd/spi-nor/{ => controllers}/aspeed-smc.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/cadence-quadspi.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/hisi-sfc.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/intel-spi-pci.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/intel-spi-platform.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/intel-spi.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/intel-spi.h (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/mtk-quadspi.c (100%)
 rename drivers/mtd/spi-nor/{ => controllers}/nxp-spifi.c (100%)
 rename drivers/mtd/spi-nor/{spi-nor.c => core.c} (100%)

diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index c1eda67d1ad2..6e816eafb312 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -24,87 +24,6 @@ config MTD_SPI_NOR_USE_4K_SECTORS
 	  Please note that some tools/drivers/filesystems may not work with
 	  4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum).
 
-config SPI_ASPEED_SMC
-	tristate "Aspeed flash controllers in SPI mode"
-	depends on ARCH_ASPEED || COMPILE_TEST
-	depends on HAS_IOMEM && OF
-	help
-	  This enables support for the Firmware Memory controller (FMC)
-	  in the Aspeed AST2500/AST2400 SoCs when attached to SPI NOR chips,
-	  and support for the SPI flash memory controller (SPI) for
-	  the host firmware. The implementation only supports SPI NOR.
-
-config SPI_CADENCE_QUADSPI
-	tristate "Cadence Quad SPI controller"
-	depends on OF && (ARM || ARM64 || COMPILE_TEST)
-	help
-	  Enable support for the Cadence Quad SPI Flash controller.
-
-	  Cadence QSPI is a specialized controller for connecting an SPI
-	  Flash over 1/2/4-bit wide bus. Enable this option if you have a
-	  device with a Cadence QSPI controller and want to access the
-	  Flash as an MTD device.
-
-config SPI_HISI_SFC
-	tristate "Hisilicon FMC SPI-NOR Flash Controller(SFC)"
-	depends on ARCH_HISI || COMPILE_TEST
-	depends on HAS_IOMEM
-	help
-	  This enables support for HiSilicon FMC SPI-NOR flash controller.
-
-config SPI_MTK_QUADSPI
-	tristate "MediaTek Quad SPI controller"
-	depends on HAS_IOMEM
-	help
-	  This enables support for the Quad SPI controller in master mode.
-	  This controller does not support generic SPI. It only supports
-	  SPI NOR.
-
-config SPI_NXP_SPIFI
-	tristate "NXP SPI Flash Interface (SPIFI)"
-	depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
-	depends on HAS_IOMEM
-	help
-	  Enable support for the NXP LPC SPI Flash Interface controller.
-
-	  SPIFI is a specialized controller for connecting serial SPI
-	  Flash. Enable this option if you have a device with a SPIFI
-	  controller and want to access the Flash as a mtd device.
-
-config SPI_INTEL_SPI
-	tristate
-
-config SPI_INTEL_SPI_PCI
-	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
-	depends on X86 && PCI
-	select SPI_INTEL_SPI
-	help
-	  This enables PCI support for the Intel PCH/PCU SPI controller in
-	  master mode. This controller is present in modern Intel hardware
-	  and is used to hold BIOS and other persistent settings. Using
-	  this driver it is possible to upgrade BIOS directly from Linux.
-
-	  Say N here unless you know what you are doing. Overwriting the
-	  SPI flash may render the system unbootable.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called intel-spi-pci.
-
-config SPI_INTEL_SPI_PLATFORM
-	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
-	depends on X86
-	select SPI_INTEL_SPI
-	help
-	  This enables platform support for the Intel PCH/PCU SPI
-	  controller in master mode. This controller is present in modern
-	  Intel hardware and is used to hold BIOS and other persistent
-	  settings. Using this driver it is possible to upgrade BIOS
-	  directly from Linux.
-
-	  Say N here unless you know what you are doing. Overwriting the
-	  SPI flash may render the system unbootable.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called intel-spi-platform.
+source "drivers/mtd/spi-nor/controllers/Kconfig"
 
 endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 9c5ed03cdc19..d6fc70ab4a32 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,10 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
+
+spi-nor-objs			:= core.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
-obj-$(CONFIG_SPI_ASPEED_SMC)	+= aspeed-smc.o
-obj-$(CONFIG_SPI_CADENCE_QUADSPI)	+= cadence-quadspi.o
-obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o
-obj-$(CONFIG_SPI_MTK_QUADSPI)    += mtk-quadspi.o
-obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
-obj-$(CONFIG_SPI_INTEL_SPI)	+= intel-spi.o
-obj-$(CONFIG_SPI_INTEL_SPI_PCI)	+= intel-spi-pci.o
-obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)	+= intel-spi-platform.o
diff --git a/drivers/mtd/spi-nor/controllers/Kconfig b/drivers/mtd/spi-nor/controllers/Kconfig
new file mode 100644
index 000000000000..a02feb201a5b
--- /dev/null
+++ b/drivers/mtd/spi-nor/controllers/Kconfig
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: GPL-2.0-only
+config SPI_ASPEED_SMC
+	tristate "Aspeed flash controllers in SPI mode"
+	depends on ARCH_ASPEED || COMPILE_TEST
+	depends on HAS_IOMEM && OF
+	help
+	  This enables support for the Firmware Memory controller (FMC)
+	  in the Aspeed AST2500/AST2400 SoCs when attached to SPI NOR chips,
+	  and support for the SPI flash memory controller (SPI) for
+	  the host firmware. The implementation only supports SPI NOR.
+
+config SPI_CADENCE_QUADSPI
+	tristate "Cadence Quad SPI controller"
+	depends on OF && (ARM || ARM64 || COMPILE_TEST)
+	help
+	  Enable support for the Cadence Quad SPI Flash controller.
+
+	  Cadence QSPI is a specialized controller for connecting an SPI
+	  Flash over 1/2/4-bit wide bus. Enable this option if you have a
+	  device with a Cadence QSPI controller and want to access the
+	  Flash as an MTD device.
+
+config SPI_HISI_SFC
+	tristate "Hisilicon FMC SPI-NOR Flash Controller(SFC)"
+	depends on ARCH_HISI || COMPILE_TEST
+	depends on HAS_IOMEM
+	help
+	  This enables support for HiSilicon FMC SPI-NOR flash controller.
+
+config SPI_MTK_QUADSPI
+	tristate "MediaTek Quad SPI controller"
+	depends on HAS_IOMEM
+	help
+	  This enables support for the Quad SPI controller in master mode.
+	  This controller does not support generic SPI. It only supports
+	  SPI NOR.
+
+config SPI_NXP_SPIFI
+	tristate "NXP SPI Flash Interface (SPIFI)"
+	depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
+	depends on HAS_IOMEM
+	help
+	  Enable support for the NXP LPC SPI Flash Interface controller.
+
+	  SPIFI is a specialized controller for connecting serial SPI
+	  Flash. Enable this option if you have a device with a SPIFI
+	  controller and want to access the Flash as a mtd device.
+
+config SPI_INTEL_SPI
+	tristate
+
+config SPI_INTEL_SPI_PCI
+	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
+	depends on X86 && PCI
+	select SPI_INTEL_SPI
+	help
+	  This enables PCI support for the Intel PCH/PCU SPI controller in
+	  master mode. This controller is present in modern Intel hardware
+	  and is used to hold BIOS and other persistent settings. Using
+	  this driver it is possible to upgrade BIOS directly from Linux.
+
+	  Say N here unless you know what you are doing. Overwriting the
+	  SPI flash may render the system unbootable.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called intel-spi-pci.
+
+config SPI_INTEL_SPI_PLATFORM
+	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
+	depends on X86
+	select SPI_INTEL_SPI
+	help
+	  This enables platform support for the Intel PCH/PCU SPI
+	  controller in master mode. This controller is present in modern
+	  Intel hardware and is used to hold BIOS and other persistent
+	  settings. Using this driver it is possible to upgrade BIOS
+	  directly from Linux.
+
+	  Say N here unless you know what you are doing. Overwriting the
+	  SPI flash may render the system unbootable.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called intel-spi-platform.
diff --git a/drivers/mtd/spi-nor/controllers/Makefile b/drivers/mtd/spi-nor/controllers/Makefile
new file mode 100644
index 000000000000..c9a39992d63d
--- /dev/null
+++ b/drivers/mtd/spi-nor/controllers/Makefile
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_SPI_ASPEED_SMC)	+= aspeed-smc.o
+obj-$(CONFIG_SPI_CADENCE_QUADSPI)	+= cadence-quadspi.o
+obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o
+obj-$(CONFIG_SPI_MTK_QUADSPI)    += mtk-quadspi.o
+obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
+obj-$(CONFIG_SPI_INTEL_SPI)	+= intel-spi.o
+obj-$(CONFIG_SPI_INTEL_SPI_PCI)	+= intel-spi-pci.o
+obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)	+= intel-spi-platform.o
diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/controllers/aspeed-smc.c
similarity index 100%
rename from drivers/mtd/spi-nor/aspeed-smc.c
rename to drivers/mtd/spi-nor/controllers/aspeed-smc.c
diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/controllers/cadence-quadspi.c
similarity index 100%
rename from drivers/mtd/spi-nor/cadence-quadspi.c
rename to drivers/mtd/spi-nor/controllers/cadence-quadspi.c
diff --git a/drivers/mtd/spi-nor/hisi-sfc.c b/drivers/mtd/spi-nor/controllers/hisi-sfc.c
similarity index 100%
rename from drivers/mtd/spi-nor/hisi-sfc.c
rename to drivers/mtd/spi-nor/controllers/hisi-sfc.c
diff --git a/drivers/mtd/spi-nor/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
similarity index 100%
rename from drivers/mtd/spi-nor/intel-spi-pci.c
rename to drivers/mtd/spi-nor/controllers/intel-spi-pci.c
diff --git a/drivers/mtd/spi-nor/intel-spi-platform.c b/drivers/mtd/spi-nor/controllers/intel-spi-platform.c
similarity index 100%
rename from drivers/mtd/spi-nor/intel-spi-platform.c
rename to drivers/mtd/spi-nor/controllers/intel-spi-platform.c
diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
similarity index 100%
rename from drivers/mtd/spi-nor/intel-spi.c
rename to drivers/mtd/spi-nor/controllers/intel-spi.c
diff --git a/drivers/mtd/spi-nor/intel-spi.h b/drivers/mtd/spi-nor/controllers/intel-spi.h
similarity index 100%
rename from drivers/mtd/spi-nor/intel-spi.h
rename to drivers/mtd/spi-nor/controllers/intel-spi.h
diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/controllers/mtk-quadspi.c
similarity index 100%
rename from drivers/mtd/spi-nor/mtk-quadspi.c
rename to drivers/mtd/spi-nor/controllers/mtk-quadspi.c
diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/controllers/nxp-spifi.c
similarity index 100%
rename from drivers/mtd/spi-nor/nxp-spifi.c
rename to drivers/mtd/spi-nor/controllers/nxp-spifi.c
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/core.c
similarity index 100%
rename from drivers/mtd/spi-nor/spi-nor.c
rename to drivers/mtd/spi-nor/core.c
-- 
2.23.0

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

* [PATCH 03/23] mtd: spi-nor: Move SFDP logic out of the core
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 02/23] mtd: spi-nor: Prepare core / manufacturer code split Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-07 14:50   ` Boris Brezillon
  2020-03-02 18:07 ` [PATCH 04/23] mtd: spi-nor: Expose stuctures and functions to manufacturer drivers Tudor.Ambarus
                   ` (20 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Tudor Ambarus <tudor.ambarus@microchip.com>

It makes the core file a bit smaller and provides better separation
between the SFDP parsing and core logic.

Keep the core.h and sfdp.h definitions private in drivers/mtd/spi-nor/.
Both expose just the definitions that are required by the core and
manufacturer drivers. None of the SPI NOR controller drivers should
include them.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |    2 +-
 drivers/mtd/spi-nor/core.c   | 1315 +---------------------------------
 drivers/mtd/spi-nor/core.h   |   36 +
 drivers/mtd/spi-nor/sfdp.c   | 1196 +++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/sfdp.h   |   98 +++
 5 files changed, 1350 insertions(+), 1297 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/core.h
 create mode 100644 drivers/mtd/spi-nor/sfdp.c
 create mode 100644 drivers/mtd/spi-nor/sfdp.h

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index d6fc70ab4a32..6bcdb6f1615a 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
-spi-nor-objs			:= core.o
+spi-nor-objs			:= core.o sfdp.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index b15e262765e1..1edcb53c4df3 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -15,7 +15,6 @@
 #include <linux/math64.h>
 #include <linux/sizes.h>
 #include <linux/slab.h>
-#include <linux/sort.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/of_platform.h>
@@ -23,6 +22,8 @@
 #include <linux/spi/flash.h>
 #include <linux/mtd/spi-nor.h>
 
+#include "core.h"
+
 /* Define max times to check status register before we give up. */
 
 /*
@@ -40,118 +41,6 @@
 #define SPI_NOR_MAX_ID_LEN	6
 #define SPI_NOR_MAX_ADDR_WIDTH	4
 
-struct sfdp_parameter_header {
-	u8		id_lsb;
-	u8		minor;
-	u8		major;
-	u8		length; /* in double words */
-	u8		parameter_table_pointer[3]; /* byte address */
-	u8		id_msb;
-};
-
-#define SFDP_PARAM_HEADER_ID(p)	(((p)->id_msb << 8) | (p)->id_lsb)
-#define SFDP_PARAM_HEADER_PTP(p) \
-	(((p)->parameter_table_pointer[2] << 16) | \
-	 ((p)->parameter_table_pointer[1] <<  8) | \
-	 ((p)->parameter_table_pointer[0] <<  0))
-
-#define SFDP_BFPT_ID		0xff00	/* Basic Flash Parameter Table */
-#define SFDP_SECTOR_MAP_ID	0xff81	/* Sector Map Table */
-#define SFDP_4BAIT_ID		0xff84  /* 4-byte Address Instruction Table */
-
-#define SFDP_SIGNATURE		0x50444653U
-#define SFDP_JESD216_MAJOR	1
-#define SFDP_JESD216_MINOR	0
-#define SFDP_JESD216A_MINOR	5
-#define SFDP_JESD216B_MINOR	6
-
-struct sfdp_header {
-	u32		signature; /* Ox50444653U <=> "SFDP" */
-	u8		minor;
-	u8		major;
-	u8		nph; /* 0-base number of parameter headers */
-	u8		unused;
-
-	/* Basic Flash Parameter Table. */
-	struct sfdp_parameter_header	bfpt_header;
-};
-
-/* Basic Flash Parameter Table */
-
-/*
- * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs.
- * They are indexed from 1 but C arrays are indexed from 0.
- */
-#define BFPT_DWORD(i)		((i) - 1)
-#define BFPT_DWORD_MAX		16
-
-/* The first version of JESD216 defined only 9 DWORDs. */
-#define BFPT_DWORD_MAX_JESD216			9
-
-/* 1st DWORD. */
-#define BFPT_DWORD1_FAST_READ_1_1_2		BIT(16)
-#define BFPT_DWORD1_ADDRESS_BYTES_MASK		GENMASK(18, 17)
-#define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY	(0x0UL << 17)
-#define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4	(0x1UL << 17)
-#define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY	(0x2UL << 17)
-#define BFPT_DWORD1_DTR				BIT(19)
-#define BFPT_DWORD1_FAST_READ_1_2_2		BIT(20)
-#define BFPT_DWORD1_FAST_READ_1_4_4		BIT(21)
-#define BFPT_DWORD1_FAST_READ_1_1_4		BIT(22)
-
-/* 5th DWORD. */
-#define BFPT_DWORD5_FAST_READ_2_2_2		BIT(0)
-#define BFPT_DWORD5_FAST_READ_4_4_4		BIT(4)
-
-/* 11th DWORD. */
-#define BFPT_DWORD11_PAGE_SIZE_SHIFT		4
-#define BFPT_DWORD11_PAGE_SIZE_MASK		GENMASK(7, 4)
-
-/* 15th DWORD. */
-
-/*
- * (from JESD216 rev B)
- * Quad Enable Requirements (QER):
- * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4
- *         reads based on instruction. DQ3/HOLD# functions are hold during
- *         instruction phase.
- * - 001b: QE is bit 1 of status register 2. It is set via Write Status with
- *         two data bytes where bit 1 of the second byte is one.
- *         [...]
- *         Writing only one byte to the status register has the side-effect of
- *         clearing status register 2, including the QE bit. The 100b code is
- *         used if writing one byte to the status register does not modify
- *         status register 2.
- * - 010b: QE is bit 6 of status register 1. It is set via Write Status with
- *         one data byte where bit 6 is one.
- *         [...]
- * - 011b: QE is bit 7 of status register 2. It is set via Write status
- *         register 2 instruction 3Eh with one data byte where bit 7 is one.
- *         [...]
- *         The status register 2 is read using instruction 3Fh.
- * - 100b: QE is bit 1 of status register 2. It is set via Write Status with
- *         two data bytes where bit 1 of the second byte is one.
- *         [...]
- *         In contrast to the 001b code, writing one byte to the status
- *         register does not modify status register 2.
- * - 101b: QE is bit 1 of status register 2. Status register 1 is read using
- *         Read Status instruction 05h. Status register2 is read using
- *         instruction 35h. QE is set via Write Status instruction 01h with
- *         two data bytes where bit 1 of the second byte is one.
- *         [...]
- */
-#define BFPT_DWORD15_QER_MASK			GENMASK(22, 20)
-#define BFPT_DWORD15_QER_NONE			(0x0UL << 20) /* Micron */
-#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY		(0x1UL << 20)
-#define BFPT_DWORD15_QER_SR1_BIT6		(0x2UL << 20) /* Macronix */
-#define BFPT_DWORD15_QER_SR2_BIT7		(0x3UL << 20)
-#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD		(0x4UL << 20)
-#define BFPT_DWORD15_QER_SR2_BIT1		(0x5UL << 20) /* Spansion */
-
-struct sfdp_bfpt {
-	u32	dwords[BFPT_DWORD_MAX];
-};
-
 /**
  * struct spi_nor_fixups - SPI NOR fixup hooks
  * @default_init: called after default flash parameters init. Used to tweak
@@ -345,8 +234,7 @@ static ssize_t spi_nor_spimem_read_data(struct spi_nor *nor, loff_t from,
  *
  * Return: number of bytes read successfully, -errno otherwise
  */
-static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
-				 u8 *buf)
+ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, u8 *buf)
 {
 	if (nor->spimem)
 		return spi_nor_spimem_read_data(nor, from, len, buf);
@@ -1271,7 +1159,7 @@ static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size)
 	return opcode;
 }
 
-static u8 spi_nor_convert_3to4_read(u8 opcode)
+u8 spi_nor_convert_3to4_read(u8 opcode)
 {
 	static const u8 spi_nor_3to4_read[][2] = {
 		{ SPINOR_OP_READ,	SPINOR_OP_READ_4B },
@@ -1496,7 +1384,7 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
  *
  * Return: the next spi nor region or NULL if last region.
  */
-static struct spi_nor_erase_region *
+struct spi_nor_erase_region *
 spi_nor_region_next(struct spi_nor_erase_region *region)
 {
 	if (spi_nor_region_is_last(region))
@@ -2125,7 +2013,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor)
+int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor)
 {
 	int ret;
 
@@ -2150,7 +2038,7 @@ static int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
+int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
 {
 	int ret;
 
@@ -2181,7 +2069,7 @@ static int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
+int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
 {
 	u8 *sr2 = nor->bouncebuf;
 	int ret;
@@ -3029,10 +2917,8 @@ spi_nor_set_read_settings(struct spi_nor_read_command *read,
 	read->proto = proto;
 }
 
-static void
-spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,
-			u8 opcode,
-			enum spi_nor_protocol proto)
+void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode,
+			     enum spi_nor_protocol proto)
 {
 	pp->opcode = opcode;
 	pp->proto = proto;
@@ -3049,7 +2935,7 @@ static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size)
 	return -EINVAL;
 }
 
-static int spi_nor_hwcaps_read2cmd(u32 hwcaps)
+int spi_nor_hwcaps_read2cmd(u32 hwcaps)
 {
 	static const int hwcaps_read2cmd[][2] = {
 		{ SNOR_HWCAPS_READ,		SNOR_CMD_READ },
@@ -3089,76 +2975,6 @@ static int spi_nor_hwcaps_pp2cmd(u32 hwcaps)
 				  ARRAY_SIZE(hwcaps_pp2cmd));
 }
 
-/*
- * Serial Flash Discoverable Parameters (SFDP) parsing.
- */
-
-/**
- * spi_nor_read_raw() - raw read of serial flash memory. read_opcode,
- *			addr_width and read_dummy members of the struct spi_nor
- *			should be previously
- * set.
- * @nor:	pointer to a 'struct spi_nor'
- * @addr:	offset in the serial flash memory
- * @len:	number of bytes to read
- * @buf:	buffer where the data is copied into (dma-safe memory)
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int spi_nor_read_raw(struct spi_nor *nor, u32 addr, size_t len, u8 *buf)
-{
-	ssize_t ret;
-
-	while (len) {
-		ret = spi_nor_read_data(nor, addr, len, buf);
-		if (ret < 0)
-			return ret;
-		if (!ret || ret > len)
-			return -EIO;
-
-		buf += ret;
-		addr += ret;
-		len -= ret;
-	}
-	return 0;
-}
-
-/**
- * spi_nor_read_sfdp() - read Serial Flash Discoverable Parameters.
- * @nor:	pointer to a 'struct spi_nor'
- * @addr:	offset in the SFDP area to start reading data from
- * @len:	number of bytes to read
- * @buf:	buffer where the SFDP data are copied into (dma-safe memory)
- *
- * Whatever the actual numbers of bytes for address and dummy cycles are
- * for (Fast) Read commands, the Read SFDP (5Ah) instruction is always
- * followed by a 3-byte address and 8 dummy clock cycles.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
-			     size_t len, void *buf)
-{
-	u8 addr_width, read_opcode, read_dummy;
-	int ret;
-
-	read_opcode = nor->read_opcode;
-	addr_width = nor->addr_width;
-	read_dummy = nor->read_dummy;
-
-	nor->read_opcode = SPINOR_OP_RDSFDP;
-	nor->addr_width = 3;
-	nor->read_dummy = 8;
-
-	ret = spi_nor_read_raw(nor, addr, len, buf);
-
-	nor->read_opcode = read_opcode;
-	nor->addr_width = addr_width;
-	nor->read_dummy = read_dummy;
-
-	return ret;
-}
-
 /**
  * spi_nor_spimem_check_op - check if the operation is supported
  *                           by controller
@@ -3279,153 +3095,14 @@ spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
 	}
 }
 
-/**
- * spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters.
- * @nor:	pointer to a 'struct spi_nor'
- * @addr:	offset in the SFDP area to start reading data from
- * @len:	number of bytes to read
- * @buf:	buffer where the SFDP data are copied into
- *
- * Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not
- * guaranteed to be dma-safe.
- *
- * Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp()
- *          otherwise.
- */
-static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr,
-					size_t len, void *buf)
-{
-	void *dma_safe_buf;
-	int ret;
-
-	dma_safe_buf = kmalloc(len, GFP_KERNEL);
-	if (!dma_safe_buf)
-		return -ENOMEM;
-
-	ret = spi_nor_read_sfdp(nor, addr, len, dma_safe_buf);
-	memcpy(buf, dma_safe_buf, len);
-	kfree(dma_safe_buf);
-
-	return ret;
-}
-
-/* Fast Read settings. */
-
-static void
-spi_nor_set_read_settings_from_bfpt(struct spi_nor_read_command *read,
-				    u16 half,
-				    enum spi_nor_protocol proto)
-{
-	read->num_mode_clocks = (half >> 5) & 0x07;
-	read->num_wait_states = (half >> 0) & 0x1f;
-	read->opcode = (half >> 8) & 0xff;
-	read->proto = proto;
-}
-
-struct sfdp_bfpt_read {
-	/* The Fast Read x-y-z hardware capability in params->hwcaps.mask. */
-	u32			hwcaps;
-
-	/*
-	 * The <supported_bit> bit in <supported_dword> BFPT DWORD tells us
-	 * whether the Fast Read x-y-z command is supported.
-	 */
-	u32			supported_dword;
-	u32			supported_bit;
-
-	/*
-	 * The half-word at offset <setting_shift> in <setting_dword> BFPT DWORD
-	 * encodes the op code, the number of mode clocks and the number of wait
-	 * states to be used by Fast Read x-y-z command.
-	 */
-	u32			settings_dword;
-	u32			settings_shift;
-
-	/* The SPI protocol for this Fast Read x-y-z command. */
-	enum spi_nor_protocol	proto;
-};
-
-static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = {
-	/* Fast Read 1-1-2 */
-	{
-		SNOR_HWCAPS_READ_1_1_2,
-		BFPT_DWORD(1), BIT(16),	/* Supported bit */
-		BFPT_DWORD(4), 0,	/* Settings */
-		SNOR_PROTO_1_1_2,
-	},
-
-	/* Fast Read 1-2-2 */
-	{
-		SNOR_HWCAPS_READ_1_2_2,
-		BFPT_DWORD(1), BIT(20),	/* Supported bit */
-		BFPT_DWORD(4), 16,	/* Settings */
-		SNOR_PROTO_1_2_2,
-	},
-
-	/* Fast Read 2-2-2 */
-	{
-		SNOR_HWCAPS_READ_2_2_2,
-		BFPT_DWORD(5),  BIT(0),	/* Supported bit */
-		BFPT_DWORD(6), 16,	/* Settings */
-		SNOR_PROTO_2_2_2,
-	},
-
-	/* Fast Read 1-1-4 */
-	{
-		SNOR_HWCAPS_READ_1_1_4,
-		BFPT_DWORD(1), BIT(22),	/* Supported bit */
-		BFPT_DWORD(3), 16,	/* Settings */
-		SNOR_PROTO_1_1_4,
-	},
-
-	/* Fast Read 1-4-4 */
-	{
-		SNOR_HWCAPS_READ_1_4_4,
-		BFPT_DWORD(1), BIT(21),	/* Supported bit */
-		BFPT_DWORD(3), 0,	/* Settings */
-		SNOR_PROTO_1_4_4,
-	},
-
-	/* Fast Read 4-4-4 */
-	{
-		SNOR_HWCAPS_READ_4_4_4,
-		BFPT_DWORD(5), BIT(4),	/* Supported bit */
-		BFPT_DWORD(7), 16,	/* Settings */
-		SNOR_PROTO_4_4_4,
-	},
-};
-
-struct sfdp_bfpt_erase {
-	/*
-	 * The half-word at offset <shift> in DWORD <dwoard> encodes the
-	 * op code and erase sector size to be used by Sector Erase commands.
-	 */
-	u32			dword;
-	u32			shift;
-};
-
-static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = {
-	/* Erase Type 1 in DWORD8 bits[15:0] */
-	{BFPT_DWORD(8), 0},
-
-	/* Erase Type 2 in DWORD8 bits[31:16] */
-	{BFPT_DWORD(8), 16},
-
-	/* Erase Type 3 in DWORD9 bits[15:0] */
-	{BFPT_DWORD(9), 0},
-
-	/* Erase Type 4 in DWORD9 bits[31:16] */
-	{BFPT_DWORD(9), 16},
-};
-
 /**
  * spi_nor_set_erase_type() - set a SPI NOR erase type
  * @erase:	pointer to a structure that describes a SPI NOR erase type
  * @size:	the size of the sector/block erased by the erase type
  * @opcode:	the SPI command op code to erase the sector/block
  */
-static void spi_nor_set_erase_type(struct spi_nor_erase_type *erase,
-				   u32 size, u8 opcode)
+void spi_nor_set_erase_type(struct spi_nor_erase_type *erase, u32 size,
+			    u8 opcode)
 {
 	erase->size = size;
 	erase->opcode = opcode;
@@ -3434,104 +3111,6 @@ static void spi_nor_set_erase_type(struct spi_nor_erase_type *erase,
 	erase->size_mask = (1 << erase->size_shift) - 1;
 }
 
-/**
- * spi_nor_set_erase_settings_from_bfpt() - set erase type settings from BFPT
- * @erase:	pointer to a structure that describes a SPI NOR erase type
- * @size:	the size of the sector/block erased by the erase type
- * @opcode:	the SPI command op code to erase the sector/block
- * @i:		erase type index as sorted in the Basic Flash Parameter Table
- *
- * The supported Erase Types will be sorted at init in ascending order, with
- * the smallest Erase Type size being the first member in the erase_type array
- * of the spi_nor_erase_map structure. Save the Erase Type index as sorted in
- * the Basic Flash Parameter Table since it will be used later on to
- * synchronize with the supported Erase Types defined in SFDP optional tables.
- */
-static void
-spi_nor_set_erase_settings_from_bfpt(struct spi_nor_erase_type *erase,
-				     u32 size, u8 opcode, u8 i)
-{
-	erase->idx = i;
-	spi_nor_set_erase_type(erase, size, opcode);
-}
-
-/**
- * spi_nor_map_cmp_erase_type() - compare the map's erase types by size
- * @l:	member in the left half of the map's erase_type array
- * @r:	member in the right half of the map's erase_type array
- *
- * Comparison function used in the sort() call to sort in ascending order the
- * map's erase types, the smallest erase type size being the first member in the
- * sorted erase_type array.
- *
- * Return: the result of @l->size - @r->size
- */
-static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
-{
-	const struct spi_nor_erase_type *left = l, *right = r;
-
-	return left->size - right->size;
-}
-
-/**
- * spi_nor_sort_erase_mask() - sort erase mask
- * @map:	the erase map of the SPI NOR
- * @erase_mask:	the erase type mask to be sorted
- *
- * Replicate the sort done for the map's erase types in BFPT: sort the erase
- * mask in ascending order with the smallest erase type size starting from
- * BIT(0) in the sorted erase mask.
- *
- * Return: sorted erase mask.
- */
-static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask)
-{
-	struct spi_nor_erase_type *erase_type = map->erase_type;
-	int i;
-	u8 sorted_erase_mask = 0;
-
-	if (!erase_mask)
-		return 0;
-
-	/* Replicate the sort done for the map's erase types. */
-	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
-		if (erase_type[i].size && erase_mask & BIT(erase_type[i].idx))
-			sorted_erase_mask |= BIT(i);
-
-	return sorted_erase_mask;
-}
-
-/**
- * spi_nor_regions_sort_erase_types() - sort erase types in each region
- * @map:	the erase map of the SPI NOR
- *
- * Function assumes that the erase types defined in the erase map are already
- * sorted in ascending order, with the smallest erase type size being the first
- * member in the erase_type array. It replicates the sort done for the map's
- * erase types. Each region's erase bitmask will indicate which erase types are
- * supported from the sorted erase types defined in the erase map.
- * Sort the all region's erase type at init in order to speed up the process of
- * finding the best erase command at runtime.
- */
-static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)
-{
-	struct spi_nor_erase_region *region = map->regions;
-	u8 region_erase_mask, sorted_erase_mask;
-
-	while (region) {
-		region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK;
-
-		sorted_erase_mask = spi_nor_sort_erase_mask(map,
-							    region_erase_mask);
-
-		/* Overwrite erase mask. */
-		region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) |
-				 sorted_erase_mask;
-
-		region = spi_nor_region_next(region);
-	}
-}
-
 /**
  * spi_nor_init_uniform_erase_map() - Initialize uniform erase map
  * @map:		the erase map of the SPI NOR
@@ -3539,8 +3118,8 @@ static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)
  *			flash memory
  * @flash_size:		the spi nor flash memory size
  */
-static void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map,
-					   u8 erase_mask, u64 flash_size)
+void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map,
+				    u8 erase_mask, u64 flash_size)
 {
 	/* Offset 0 with erase_mask and SNOR_LAST_REGION bit set */
 	map->uniform_region.offset = (erase_mask & SNOR_ERASE_TYPE_MASK) |
@@ -3550,11 +3129,10 @@ static void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map,
 	map->uniform_erase_type = erase_mask;
 }
 
-static int
-spi_nor_post_bfpt_fixups(struct spi_nor *nor,
-			 const struct sfdp_parameter_header *bfpt_header,
-			 const struct sfdp_bfpt *bfpt,
-			 struct spi_nor_flash_parameter *params)
+int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
+			     const struct sfdp_parameter_header *bfpt_header,
+			     const struct sfdp_bfpt *bfpt,
+			     struct spi_nor_flash_parameter *params)
 {
 	if (nor->info->fixups && nor->info->fixups->post_bfpt)
 		return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt,
@@ -3563,861 +3141,6 @@ spi_nor_post_bfpt_fixups(struct spi_nor *nor,
 	return 0;
 }
 
-/**
- * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table.
- * @nor:		pointer to a 'struct spi_nor'
- * @bfpt_header:	pointer to the 'struct sfdp_parameter_header' describing
- *			the Basic Flash Parameter Table length and version
- * @params:		pointer to the 'struct spi_nor_flash_parameter' to be
- *			filled
- *
- * The Basic Flash Parameter Table is the main and only mandatory table as
- * defined by the SFDP (JESD216) specification.
- * It provides us with the total size (memory density) of the data array and
- * the number of address bytes for Fast Read, Page Program and Sector Erase
- * commands.
- * For Fast READ commands, it also gives the number of mode clock cycles and
- * wait states (regrouped in the number of dummy clock cycles) for each
- * supported instruction op code.
- * For Page Program, the page size is now available since JESD216 rev A, however
- * the supported instruction op codes are still not provided.
- * For Sector Erase commands, this table stores the supported instruction op
- * codes and the associated sector sizes.
- * Finally, the Quad Enable Requirements (QER) are also available since JESD216
- * rev A. The QER bits encode the manufacturer dependent procedure to be
- * executed to set the Quad Enable (QE) bit in some internal register of the
- * Quad SPI memory. Indeed the QE bit, when it exists, must be set before
- * sending any Quad SPI command to the memory. Actually, setting the QE bit
- * tells the memory to reassign its WP# and HOLD#/RESET# pins to functions IO2
- * and IO3 hence enabling 4 (Quad) I/O lines.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int spi_nor_parse_bfpt(struct spi_nor *nor,
-			      const struct sfdp_parameter_header *bfpt_header,
-			      struct spi_nor_flash_parameter *params)
-{
-	struct spi_nor_erase_map *map = &params->erase_map;
-	struct spi_nor_erase_type *erase_type = map->erase_type;
-	struct sfdp_bfpt bfpt;
-	size_t len;
-	int i, cmd, err;
-	u32 addr;
-	u16 half;
-	u8 erase_mask;
-
-	/* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */
-	if (bfpt_header->length < BFPT_DWORD_MAX_JESD216)
-		return -EINVAL;
-
-	/* Read the Basic Flash Parameter Table. */
-	len = min_t(size_t, sizeof(bfpt),
-		    bfpt_header->length * sizeof(u32));
-	addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
-	memset(&bfpt, 0, sizeof(bfpt));
-	err = spi_nor_read_sfdp_dma_unsafe(nor,  addr, len, &bfpt);
-	if (err < 0)
-		return err;
-
-	/* Fix endianness of the BFPT DWORDs. */
-	le32_to_cpu_array(bfpt.dwords, BFPT_DWORD_MAX);
-
-	/* Number of address bytes. */
-	switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
-	case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY:
-		nor->addr_width = 3;
-		break;
-
-	case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY:
-		nor->addr_width = 4;
-		break;
-
-	default:
-		break;
-	}
-
-	/* Flash Memory Density (in bits). */
-	params->size = bfpt.dwords[BFPT_DWORD(2)];
-	if (params->size & BIT(31)) {
-		params->size &= ~BIT(31);
-
-		/*
-		 * Prevent overflows on params->size. Anyway, a NOR of 2^64
-		 * bits is unlikely to exist so this error probably means
-		 * the BFPT we are reading is corrupted/wrong.
-		 */
-		if (params->size > 63)
-			return -EINVAL;
-
-		params->size = 1ULL << params->size;
-	} else {
-		params->size++;
-	}
-	params->size >>= 3; /* Convert to bytes. */
-
-	/* Fast Read settings. */
-	for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_reads); i++) {
-		const struct sfdp_bfpt_read *rd = &sfdp_bfpt_reads[i];
-		struct spi_nor_read_command *read;
-
-		if (!(bfpt.dwords[rd->supported_dword] & rd->supported_bit)) {
-			params->hwcaps.mask &= ~rd->hwcaps;
-			continue;
-		}
-
-		params->hwcaps.mask |= rd->hwcaps;
-		cmd = spi_nor_hwcaps_read2cmd(rd->hwcaps);
-		read = &params->reads[cmd];
-		half = bfpt.dwords[rd->settings_dword] >> rd->settings_shift;
-		spi_nor_set_read_settings_from_bfpt(read, half, rd->proto);
-	}
-
-	/*
-	 * Sector Erase settings. Reinitialize the uniform erase map using the
-	 * Erase Types defined in the bfpt table.
-	 */
-	erase_mask = 0;
-	memset(&params->erase_map, 0, sizeof(params->erase_map));
-	for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) {
-		const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i];
-		u32 erasesize;
-		u8 opcode;
-
-		half = bfpt.dwords[er->dword] >> er->shift;
-		erasesize = half & 0xff;
-
-		/* erasesize == 0 means this Erase Type is not supported. */
-		if (!erasesize)
-			continue;
-
-		erasesize = 1U << erasesize;
-		opcode = (half >> 8) & 0xff;
-		erase_mask |= BIT(i);
-		spi_nor_set_erase_settings_from_bfpt(&erase_type[i], erasesize,
-						     opcode, i);
-	}
-	spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
-	/*
-	 * Sort all the map's Erase Types in ascending order with the smallest
-	 * erase size being the first member in the erase_type array.
-	 */
-	sort(erase_type, SNOR_ERASE_TYPE_MAX, sizeof(erase_type[0]),
-	     spi_nor_map_cmp_erase_type, NULL);
-	/*
-	 * Sort the erase types in the uniform region in order to update the
-	 * uniform_erase_type bitmask. The bitmask will be used later on when
-	 * selecting the uniform erase.
-	 */
-	spi_nor_regions_sort_erase_types(map);
-	map->uniform_erase_type = map->uniform_region.offset &
-				  SNOR_ERASE_TYPE_MASK;
-
-	/* Stop here if not JESD216 rev A or later. */
-	if (bfpt_header->length < BFPT_DWORD_MAX)
-		return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt,
-						params);
-
-	/* Page size: this field specifies 'N' so the page size = 2^N bytes. */
-	params->page_size = bfpt.dwords[BFPT_DWORD(11)];
-	params->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK;
-	params->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT;
-	params->page_size = 1U << params->page_size;
-
-	/* Quad Enable Requirements. */
-	switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) {
-	case BFPT_DWORD15_QER_NONE:
-		params->quad_enable = NULL;
-		break;
-
-	case BFPT_DWORD15_QER_SR2_BIT1_BUGGY:
-		/*
-		 * Writing only one byte to the Status Register has the
-		 * side-effect of clearing Status Register 2.
-		 */
-	case BFPT_DWORD15_QER_SR2_BIT1_NO_RD:
-		/*
-		 * Read Configuration Register (35h) instruction is not
-		 * supported.
-		 */
-		nor->flags |= SNOR_F_HAS_16BIT_SR | SNOR_F_NO_READ_CR;
-		params->quad_enable = spi_nor_sr2_bit1_quad_enable;
-		break;
-
-	case BFPT_DWORD15_QER_SR1_BIT6:
-		nor->flags &= ~SNOR_F_HAS_16BIT_SR;
-		params->quad_enable = spi_nor_sr1_bit6_quad_enable;
-		break;
-
-	case BFPT_DWORD15_QER_SR2_BIT7:
-		nor->flags &= ~SNOR_F_HAS_16BIT_SR;
-		params->quad_enable = spi_nor_sr2_bit7_quad_enable;
-		break;
-
-	case BFPT_DWORD15_QER_SR2_BIT1:
-		/*
-		 * JESD216 rev B or later does not specify if writing only one
-		 * byte to the Status Register clears or not the Status
-		 * Register 2, so let's be cautious and keep the default
-		 * assumption of a 16-bit Write Status (01h) command.
-		 */
-		nor->flags |= SNOR_F_HAS_16BIT_SR;
-
-		params->quad_enable = spi_nor_sr2_bit1_quad_enable;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params);
-}
-
-#define SMPT_CMD_ADDRESS_LEN_MASK		GENMASK(23, 22)
-#define SMPT_CMD_ADDRESS_LEN_0			(0x0UL << 22)
-#define SMPT_CMD_ADDRESS_LEN_3			(0x1UL << 22)
-#define SMPT_CMD_ADDRESS_LEN_4			(0x2UL << 22)
-#define SMPT_CMD_ADDRESS_LEN_USE_CURRENT	(0x3UL << 22)
-
-#define SMPT_CMD_READ_DUMMY_MASK		GENMASK(19, 16)
-#define SMPT_CMD_READ_DUMMY_SHIFT		16
-#define SMPT_CMD_READ_DUMMY(_cmd) \
-	(((_cmd) & SMPT_CMD_READ_DUMMY_MASK) >> SMPT_CMD_READ_DUMMY_SHIFT)
-#define SMPT_CMD_READ_DUMMY_IS_VARIABLE		0xfUL
-
-#define SMPT_CMD_READ_DATA_MASK			GENMASK(31, 24)
-#define SMPT_CMD_READ_DATA_SHIFT		24
-#define SMPT_CMD_READ_DATA(_cmd) \
-	(((_cmd) & SMPT_CMD_READ_DATA_MASK) >> SMPT_CMD_READ_DATA_SHIFT)
-
-#define SMPT_CMD_OPCODE_MASK			GENMASK(15, 8)
-#define SMPT_CMD_OPCODE_SHIFT			8
-#define SMPT_CMD_OPCODE(_cmd) \
-	(((_cmd) & SMPT_CMD_OPCODE_MASK) >> SMPT_CMD_OPCODE_SHIFT)
-
-#define SMPT_MAP_REGION_COUNT_MASK		GENMASK(23, 16)
-#define SMPT_MAP_REGION_COUNT_SHIFT		16
-#define SMPT_MAP_REGION_COUNT(_header) \
-	((((_header) & SMPT_MAP_REGION_COUNT_MASK) >> \
-	  SMPT_MAP_REGION_COUNT_SHIFT) + 1)
-
-#define SMPT_MAP_ID_MASK			GENMASK(15, 8)
-#define SMPT_MAP_ID_SHIFT			8
-#define SMPT_MAP_ID(_header) \
-	(((_header) & SMPT_MAP_ID_MASK) >> SMPT_MAP_ID_SHIFT)
-
-#define SMPT_MAP_REGION_SIZE_MASK		GENMASK(31, 8)
-#define SMPT_MAP_REGION_SIZE_SHIFT		8
-#define SMPT_MAP_REGION_SIZE(_region) \
-	(((((_region) & SMPT_MAP_REGION_SIZE_MASK) >> \
-	   SMPT_MAP_REGION_SIZE_SHIFT) + 1) * 256)
-
-#define SMPT_MAP_REGION_ERASE_TYPE_MASK		GENMASK(3, 0)
-#define SMPT_MAP_REGION_ERASE_TYPE(_region) \
-	((_region) & SMPT_MAP_REGION_ERASE_TYPE_MASK)
-
-#define SMPT_DESC_TYPE_MAP			BIT(1)
-#define SMPT_DESC_END				BIT(0)
-
-/**
- * spi_nor_smpt_addr_width() - return the address width used in the
- *			       configuration detection command.
- * @nor:	pointer to a 'struct spi_nor'
- * @settings:	configuration detection command descriptor, dword1
- */
-static u8 spi_nor_smpt_addr_width(const struct spi_nor *nor, const u32 settings)
-{
-	switch (settings & SMPT_CMD_ADDRESS_LEN_MASK) {
-	case SMPT_CMD_ADDRESS_LEN_0:
-		return 0;
-	case SMPT_CMD_ADDRESS_LEN_3:
-		return 3;
-	case SMPT_CMD_ADDRESS_LEN_4:
-		return 4;
-	case SMPT_CMD_ADDRESS_LEN_USE_CURRENT:
-		/* fall through */
-	default:
-		return nor->addr_width;
-	}
-}
-
-/**
- * spi_nor_smpt_read_dummy() - return the configuration detection command read
- *			       latency, in clock cycles.
- * @nor:	pointer to a 'struct spi_nor'
- * @settings:	configuration detection command descriptor, dword1
- *
- * Return: the number of dummy cycles for an SMPT read
- */
-static u8 spi_nor_smpt_read_dummy(const struct spi_nor *nor, const u32 settings)
-{
-	u8 read_dummy = SMPT_CMD_READ_DUMMY(settings);
-
-	if (read_dummy == SMPT_CMD_READ_DUMMY_IS_VARIABLE)
-		return nor->read_dummy;
-	return read_dummy;
-}
-
-/**
- * spi_nor_get_map_in_use() - get the configuration map in use
- * @nor:	pointer to a 'struct spi_nor'
- * @smpt:	pointer to the sector map parameter table
- * @smpt_len:	sector map parameter table length
- *
- * Return: pointer to the map in use, ERR_PTR(-errno) otherwise.
- */
-static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
-					 u8 smpt_len)
-{
-	const u32 *ret;
-	u8 *buf;
-	u32 addr;
-	int err;
-	u8 i;
-	u8 addr_width, read_opcode, read_dummy;
-	u8 read_data_mask, map_id;
-
-	/* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */
-	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
-	if (!buf)
-		return ERR_PTR(-ENOMEM);
-
-	addr_width = nor->addr_width;
-	read_dummy = nor->read_dummy;
-	read_opcode = nor->read_opcode;
-
-	map_id = 0;
-	/* Determine if there are any optional Detection Command Descriptors */
-	for (i = 0; i < smpt_len; i += 2) {
-		if (smpt[i] & SMPT_DESC_TYPE_MAP)
-			break;
-
-		read_data_mask = SMPT_CMD_READ_DATA(smpt[i]);
-		nor->addr_width = spi_nor_smpt_addr_width(nor, smpt[i]);
-		nor->read_dummy = spi_nor_smpt_read_dummy(nor, smpt[i]);
-		nor->read_opcode = SMPT_CMD_OPCODE(smpt[i]);
-		addr = smpt[i + 1];
-
-		err = spi_nor_read_raw(nor, addr, 1, buf);
-		if (err) {
-			ret = ERR_PTR(err);
-			goto out;
-		}
-
-		/*
-		 * Build an index value that is used to select the Sector Map
-		 * Configuration that is currently in use.
-		 */
-		map_id = map_id << 1 | !!(*buf & read_data_mask);
-	}
-
-	/*
-	 * If command descriptors are provided, they always precede map
-	 * descriptors in the table. There is no need to start the iteration
-	 * over smpt array all over again.
-	 *
-	 * Find the matching configuration map.
-	 */
-	ret = ERR_PTR(-EINVAL);
-	while (i < smpt_len) {
-		if (SMPT_MAP_ID(smpt[i]) == map_id) {
-			ret = smpt + i;
-			break;
-		}
-
-		/*
-		 * If there are no more configuration map descriptors and no
-		 * configuration ID matched the configuration identifier, the
-		 * sector address map is unknown.
-		 */
-		if (smpt[i] & SMPT_DESC_END)
-			break;
-
-		/* increment the table index to the next map */
-		i += SMPT_MAP_REGION_COUNT(smpt[i]) + 1;
-	}
-
-	/* fall through */
-out:
-	kfree(buf);
-	nor->addr_width = addr_width;
-	nor->read_dummy = read_dummy;
-	nor->read_opcode = read_opcode;
-	return ret;
-}
-
-/**
- * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid
- * @region:	pointer to a structure that describes a SPI NOR erase region
- * @erase:	pointer to a structure that describes a SPI NOR erase type
- * @erase_type:	erase type bitmask
- */
-static void
-spi_nor_region_check_overlay(struct spi_nor_erase_region *region,
-			     const struct spi_nor_erase_type *erase,
-			     const u8 erase_type)
-{
-	int i;
-
-	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
-		if (!(erase_type & BIT(i)))
-			continue;
-		if (region->size & erase[i].size_mask) {
-			spi_nor_region_mark_overlay(region);
-			return;
-		}
-	}
-}
-
-/**
- * spi_nor_init_non_uniform_erase_map() - initialize the non-uniform erase map
- * @nor:	pointer to a 'struct spi_nor'
- * @params:     pointer to a duplicate 'struct spi_nor_flash_parameter' that is
- *              used for storing SFDP parsed data
- * @smpt:	pointer to the sector map parameter table
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int
-spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
-				   struct spi_nor_flash_parameter *params,
-				   const u32 *smpt)
-{
-	struct spi_nor_erase_map *map = &params->erase_map;
-	struct spi_nor_erase_type *erase = map->erase_type;
-	struct spi_nor_erase_region *region;
-	u64 offset;
-	u32 region_count;
-	int i, j;
-	u8 uniform_erase_type, save_uniform_erase_type;
-	u8 erase_type, regions_erase_type;
-
-	region_count = SMPT_MAP_REGION_COUNT(*smpt);
-	/*
-	 * The regions will be freed when the driver detaches from the
-	 * device.
-	 */
-	region = devm_kcalloc(nor->dev, region_count, sizeof(*region),
-			      GFP_KERNEL);
-	if (!region)
-		return -ENOMEM;
-	map->regions = region;
-
-	uniform_erase_type = 0xff;
-	regions_erase_type = 0;
-	offset = 0;
-	/* Populate regions. */
-	for (i = 0; i < region_count; i++) {
-		j = i + 1; /* index for the region dword */
-		region[i].size = SMPT_MAP_REGION_SIZE(smpt[j]);
-		erase_type = SMPT_MAP_REGION_ERASE_TYPE(smpt[j]);
-		region[i].offset = offset | erase_type;
-
-		spi_nor_region_check_overlay(&region[i], erase, erase_type);
-
-		/*
-		 * Save the erase types that are supported in all regions and
-		 * can erase the entire flash memory.
-		 */
-		uniform_erase_type &= erase_type;
-
-		/*
-		 * regions_erase_type mask will indicate all the erase types
-		 * supported in this configuration map.
-		 */
-		regions_erase_type |= erase_type;
-
-		offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
-			 region[i].size;
-	}
-
-	save_uniform_erase_type = map->uniform_erase_type;
-	map->uniform_erase_type = spi_nor_sort_erase_mask(map,
-							  uniform_erase_type);
-
-	if (!regions_erase_type) {
-		/*
-		 * Roll back to the previous uniform_erase_type mask, SMPT is
-		 * broken.
-		 */
-		map->uniform_erase_type = save_uniform_erase_type;
-		return -EINVAL;
-	}
-
-	/*
-	 * BFPT advertises all the erase types supported by all the possible
-	 * map configurations. Mask out the erase types that are not supported
-	 * by the current map configuration.
-	 */
-	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
-		if (!(regions_erase_type & BIT(erase[i].idx)))
-			spi_nor_set_erase_type(&erase[i], 0, 0xFF);
-
-	spi_nor_region_mark_end(&region[i - 1]);
-
-	return 0;
-}
-
-/**
- * spi_nor_parse_smpt() - parse Sector Map Parameter Table
- * @nor:		pointer to a 'struct spi_nor'
- * @smpt_header:	sector map parameter table header
- * @params:		pointer to a duplicate 'struct spi_nor_flash_parameter'
- *                      that is used for storing SFDP parsed data
- *
- * This table is optional, but when available, we parse it to identify the
- * location and size of sectors within the main data array of the flash memory
- * device and to identify which Erase Types are supported by each sector.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int spi_nor_parse_smpt(struct spi_nor *nor,
-			      const struct sfdp_parameter_header *smpt_header,
-			      struct spi_nor_flash_parameter *params)
-{
-	const u32 *sector_map;
-	u32 *smpt;
-	size_t len;
-	u32 addr;
-	int ret;
-
-	/* Read the Sector Map Parameter Table. */
-	len = smpt_header->length * sizeof(*smpt);
-	smpt = kmalloc(len, GFP_KERNEL);
-	if (!smpt)
-		return -ENOMEM;
-
-	addr = SFDP_PARAM_HEADER_PTP(smpt_header);
-	ret = spi_nor_read_sfdp(nor, addr, len, smpt);
-	if (ret)
-		goto out;
-
-	/* Fix endianness of the SMPT DWORDs. */
-	le32_to_cpu_array(smpt, smpt_header->length);
-
-	sector_map = spi_nor_get_map_in_use(nor, smpt, smpt_header->length);
-	if (IS_ERR(sector_map)) {
-		ret = PTR_ERR(sector_map);
-		goto out;
-	}
-
-	ret = spi_nor_init_non_uniform_erase_map(nor, params, sector_map);
-	if (ret)
-		goto out;
-
-	spi_nor_regions_sort_erase_types(&params->erase_map);
-	/* fall through */
-out:
-	kfree(smpt);
-	return ret;
-}
-
-#define SFDP_4BAIT_DWORD_MAX	2
-
-struct sfdp_4bait {
-	/* The hardware capability. */
-	u32		hwcaps;
-
-	/*
-	 * The <supported_bit> bit in DWORD1 of the 4BAIT tells us whether
-	 * the associated 4-byte address op code is supported.
-	 */
-	u32		supported_bit;
-};
-
-/**
- * spi_nor_parse_4bait() - parse the 4-Byte Address Instruction Table
- * @nor:		pointer to a 'struct spi_nor'.
- * @param_header:	pointer to the 'struct sfdp_parameter_header' describing
- *			the 4-Byte Address Instruction Table length and version.
- * @params:		pointer to the 'struct spi_nor_flash_parameter' to be.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int spi_nor_parse_4bait(struct spi_nor *nor,
-			       const struct sfdp_parameter_header *param_header,
-			       struct spi_nor_flash_parameter *params)
-{
-	static const struct sfdp_4bait reads[] = {
-		{ SNOR_HWCAPS_READ,		BIT(0) },
-		{ SNOR_HWCAPS_READ_FAST,	BIT(1) },
-		{ SNOR_HWCAPS_READ_1_1_2,	BIT(2) },
-		{ SNOR_HWCAPS_READ_1_2_2,	BIT(3) },
-		{ SNOR_HWCAPS_READ_1_1_4,	BIT(4) },
-		{ SNOR_HWCAPS_READ_1_4_4,	BIT(5) },
-		{ SNOR_HWCAPS_READ_1_1_1_DTR,	BIT(13) },
-		{ SNOR_HWCAPS_READ_1_2_2_DTR,	BIT(14) },
-		{ SNOR_HWCAPS_READ_1_4_4_DTR,	BIT(15) },
-	};
-	static const struct sfdp_4bait programs[] = {
-		{ SNOR_HWCAPS_PP,		BIT(6) },
-		{ SNOR_HWCAPS_PP_1_1_4,		BIT(7) },
-		{ SNOR_HWCAPS_PP_1_4_4,		BIT(8) },
-	};
-	static const struct sfdp_4bait erases[SNOR_ERASE_TYPE_MAX] = {
-		{ 0u /* not used */,		BIT(9) },
-		{ 0u /* not used */,		BIT(10) },
-		{ 0u /* not used */,		BIT(11) },
-		{ 0u /* not used */,		BIT(12) },
-	};
-	struct spi_nor_pp_command *params_pp = params->page_programs;
-	struct spi_nor_erase_map *map = &params->erase_map;
-	struct spi_nor_erase_type *erase_type = map->erase_type;
-	u32 *dwords;
-	size_t len;
-	u32 addr, discard_hwcaps, read_hwcaps, pp_hwcaps, erase_mask;
-	int i, ret;
-
-	if (param_header->major != SFDP_JESD216_MAJOR ||
-	    param_header->length < SFDP_4BAIT_DWORD_MAX)
-		return -EINVAL;
-
-	/* Read the 4-byte Address Instruction Table. */
-	len = sizeof(*dwords) * SFDP_4BAIT_DWORD_MAX;
-
-	/* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */
-	dwords = kmalloc(len, GFP_KERNEL);
-	if (!dwords)
-		return -ENOMEM;
-
-	addr = SFDP_PARAM_HEADER_PTP(param_header);
-	ret = spi_nor_read_sfdp(nor, addr, len, dwords);
-	if (ret)
-		goto out;
-
-	/* Fix endianness of the 4BAIT DWORDs. */
-	le32_to_cpu_array(dwords, SFDP_4BAIT_DWORD_MAX);
-
-	/*
-	 * Compute the subset of (Fast) Read commands for which the 4-byte
-	 * version is supported.
-	 */
-	discard_hwcaps = 0;
-	read_hwcaps = 0;
-	for (i = 0; i < ARRAY_SIZE(reads); i++) {
-		const struct sfdp_4bait *read = &reads[i];
-
-		discard_hwcaps |= read->hwcaps;
-		if ((params->hwcaps.mask & read->hwcaps) &&
-		    (dwords[0] & read->supported_bit))
-			read_hwcaps |= read->hwcaps;
-	}
-
-	/*
-	 * Compute the subset of Page Program commands for which the 4-byte
-	 * version is supported.
-	 */
-	pp_hwcaps = 0;
-	for (i = 0; i < ARRAY_SIZE(programs); i++) {
-		const struct sfdp_4bait *program = &programs[i];
-
-		/*
-		 * The 4 Byte Address Instruction (Optional) Table is the only
-		 * SFDP table that indicates support for Page Program Commands.
-		 * Bypass the params->hwcaps.mask and consider 4BAIT the biggest
-		 * authority for specifying Page Program support.
-		 */
-		discard_hwcaps |= program->hwcaps;
-		if (dwords[0] & program->supported_bit)
-			pp_hwcaps |= program->hwcaps;
-	}
-
-	/*
-	 * Compute the subset of Sector Erase commands for which the 4-byte
-	 * version is supported.
-	 */
-	erase_mask = 0;
-	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
-		const struct sfdp_4bait *erase = &erases[i];
-
-		if (dwords[0] & erase->supported_bit)
-			erase_mask |= BIT(i);
-	}
-
-	/* Replicate the sort done for the map's erase types in BFPT. */
-	erase_mask = spi_nor_sort_erase_mask(map, erase_mask);
-
-	/*
-	 * We need at least one 4-byte op code per read, program and erase
-	 * operation; the .read(), .write() and .erase() hooks share the
-	 * nor->addr_width value.
-	 */
-	if (!read_hwcaps || !pp_hwcaps || !erase_mask)
-		goto out;
-
-	/*
-	 * Discard all operations from the 4-byte instruction set which are
-	 * not supported by this memory.
-	 */
-	params->hwcaps.mask &= ~discard_hwcaps;
-	params->hwcaps.mask |= (read_hwcaps | pp_hwcaps);
-
-	/* Use the 4-byte address instruction set. */
-	for (i = 0; i < SNOR_CMD_READ_MAX; i++) {
-		struct spi_nor_read_command *read_cmd = &params->reads[i];
-
-		read_cmd->opcode = spi_nor_convert_3to4_read(read_cmd->opcode);
-	}
-
-	/* 4BAIT is the only SFDP table that indicates page program support. */
-	if (pp_hwcaps & SNOR_HWCAPS_PP)
-		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP],
-					SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1);
-	if (pp_hwcaps & SNOR_HWCAPS_PP_1_1_4)
-		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP_1_1_4],
-					SPINOR_OP_PP_1_1_4_4B,
-					SNOR_PROTO_1_1_4);
-	if (pp_hwcaps & SNOR_HWCAPS_PP_1_4_4)
-		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP_1_4_4],
-					SPINOR_OP_PP_1_4_4_4B,
-					SNOR_PROTO_1_4_4);
-
-	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
-		if (erase_mask & BIT(i))
-			erase_type[i].opcode = (dwords[1] >>
-						erase_type[i].idx * 8) & 0xFF;
-		else
-			spi_nor_set_erase_type(&erase_type[i], 0u, 0xFF);
-	}
-
-	/*
-	 * We set SNOR_F_HAS_4BAIT in order to skip spi_nor_set_4byte_opcodes()
-	 * later because we already did the conversion to 4byte opcodes. Also,
-	 * this latest function implements a legacy quirk for the erase size of
-	 * Spansion memory. However this quirk is no longer needed with new
-	 * SFDP compliant memories.
-	 */
-	nor->addr_width = 4;
-	nor->flags |= SNOR_F_4B_OPCODES | SNOR_F_HAS_4BAIT;
-
-	/* fall through */
-out:
-	kfree(dwords);
-	return ret;
-}
-
-/**
- * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
- * @nor:		pointer to a 'struct spi_nor'
- * @params:		pointer to the 'struct spi_nor_flash_parameter' to be
- *			filled
- *
- * The Serial Flash Discoverable Parameters are described by the JEDEC JESD216
- * specification. This is a standard which tends to supported by almost all
- * (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at
- * runtime the main parameters needed to perform basic SPI flash operations such
- * as Fast Read, Page Program or Sector Erase commands.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int spi_nor_parse_sfdp(struct spi_nor *nor,
-			      struct spi_nor_flash_parameter *params)
-{
-	const struct sfdp_parameter_header *param_header, *bfpt_header;
-	struct sfdp_parameter_header *param_headers = NULL;
-	struct sfdp_header header;
-	struct device *dev = nor->dev;
-	size_t psize;
-	int i, err;
-
-	/* Get the SFDP header. */
-	err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
-	if (err < 0)
-		return err;
-
-	/* Check the SFDP header version. */
-	if (le32_to_cpu(header.signature) != SFDP_SIGNATURE ||
-	    header.major != SFDP_JESD216_MAJOR)
-		return -EINVAL;
-
-	/*
-	 * Verify that the first and only mandatory parameter header is a
-	 * Basic Flash Parameter Table header as specified in JESD216.
-	 */
-	bfpt_header = &header.bfpt_header;
-	if (SFDP_PARAM_HEADER_ID(bfpt_header) != SFDP_BFPT_ID ||
-	    bfpt_header->major != SFDP_JESD216_MAJOR)
-		return -EINVAL;
-
-	/*
-	 * Allocate memory then read all parameter headers with a single
-	 * Read SFDP command. These parameter headers will actually be parsed
-	 * twice: a first time to get the latest revision of the basic flash
-	 * parameter table, then a second time to handle the supported optional
-	 * tables.
-	 * Hence we read the parameter headers once for all to reduce the
-	 * processing time. Also we use kmalloc() instead of devm_kmalloc()
-	 * because we don't need to keep these parameter headers: the allocated
-	 * memory is always released with kfree() before exiting this function.
-	 */
-	if (header.nph) {
-		psize = header.nph * sizeof(*param_headers);
-
-		param_headers = kmalloc(psize, GFP_KERNEL);
-		if (!param_headers)
-			return -ENOMEM;
-
-		err = spi_nor_read_sfdp(nor, sizeof(header),
-					psize, param_headers);
-		if (err < 0) {
-			dev_dbg(dev, "failed to read SFDP parameter headers\n");
-			goto exit;
-		}
-	}
-
-	/*
-	 * Check other parameter headers to get the latest revision of
-	 * the basic flash parameter table.
-	 */
-	for (i = 0; i < header.nph; i++) {
-		param_header = &param_headers[i];
-
-		if (SFDP_PARAM_HEADER_ID(param_header) == SFDP_BFPT_ID &&
-		    param_header->major == SFDP_JESD216_MAJOR &&
-		    (param_header->minor > bfpt_header->minor ||
-		     (param_header->minor == bfpt_header->minor &&
-		      param_header->length > bfpt_header->length)))
-			bfpt_header = param_header;
-	}
-
-	err = spi_nor_parse_bfpt(nor, bfpt_header, params);
-	if (err)
-		goto exit;
-
-	/* Parse optional parameter tables. */
-	for (i = 0; i < header.nph; i++) {
-		param_header = &param_headers[i];
-
-		switch (SFDP_PARAM_HEADER_ID(param_header)) {
-		case SFDP_SECTOR_MAP_ID:
-			err = spi_nor_parse_smpt(nor, param_header, params);
-			break;
-
-		case SFDP_4BAIT_ID:
-			err = spi_nor_parse_4bait(nor, param_header, params);
-			break;
-
-		default:
-			break;
-		}
-
-		if (err) {
-			dev_warn(dev, "Failed to parse optional parameter table: %04x\n",
-				 SFDP_PARAM_HEADER_ID(param_header));
-			/*
-			 * Let's not drop all information we extracted so far
-			 * if optional table parsers fail. In case of failing,
-			 * each optional parser is responsible to roll back to
-			 * the previously known spi_nor data.
-			 */
-			err = 0;
-		}
-	}
-
-exit:
-	kfree(param_headers);
-	return err;
-}
-
 static int spi_nor_select_read(struct spi_nor *nor,
 			       u32 shared_hwcaps)
 {
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
new file mode 100644
index 000000000000..e1256fe50d12
--- /dev/null
+++ b/drivers/mtd/spi-nor/core.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#ifndef __LINUX_MTD_SPI_NOR_INTERNAL_H
+#define __LINUX_MTD_SPI_NOR_INTERNAL_H
+
+#include "sfdp.h"
+
+int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor);
+int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor);
+int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor);
+
+ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
+			  u8 *buf);
+
+int spi_nor_hwcaps_read2cmd(u32 hwcaps);
+u8 spi_nor_convert_3to4_read(u8 opcode);
+void spi_nor_set_pp_settings(struct spi_nor_pp_command *pp, u8 opcode,
+			     enum spi_nor_protocol proto);
+
+void spi_nor_set_erase_type(struct spi_nor_erase_type *erase, u32 size,
+			    u8 opcode);
+struct spi_nor_erase_region *
+spi_nor_region_next(struct spi_nor_erase_region *region);
+void spi_nor_init_uniform_erase_map(struct spi_nor_erase_map *map,
+				    u8 erase_mask, u64 flash_size);
+
+int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
+			     const struct sfdp_parameter_header *bfpt_header,
+			     const struct sfdp_bfpt *bfpt,
+			     struct spi_nor_flash_parameter *params);
+
+#endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
new file mode 100644
index 000000000000..b790c3ec871f
--- /dev/null
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -0,0 +1,1196 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/slab.h>
+#include <linux/sort.h>
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+#define SFDP_PARAM_HEADER_ID(p)	(((p)->id_msb << 8) | (p)->id_lsb)
+#define SFDP_PARAM_HEADER_PTP(p) \
+	(((p)->parameter_table_pointer[2] << 16) | \
+	 ((p)->parameter_table_pointer[1] <<  8) | \
+	 ((p)->parameter_table_pointer[0] <<  0))
+
+#define SFDP_BFPT_ID		0xff00	/* Basic Flash Parameter Table */
+#define SFDP_SECTOR_MAP_ID	0xff81	/* Sector Map Table */
+#define SFDP_4BAIT_ID		0xff84  /* 4-byte Address Instruction Table */
+
+#define SFDP_SIGNATURE		0x50444653U
+#define SFDP_JESD216_MAJOR	1
+#define SFDP_JESD216_MINOR	0
+#define SFDP_JESD216A_MINOR	5
+#define SFDP_JESD216B_MINOR	6
+
+struct sfdp_header {
+	u32		signature; /* Ox50444653U <=> "SFDP" */
+	u8		minor;
+	u8		major;
+	u8		nph; /* 0-base number of parameter headers */
+	u8		unused;
+
+	/* Basic Flash Parameter Table. */
+	struct sfdp_parameter_header	bfpt_header;
+};
+
+/* Fast Read settings. */
+struct sfdp_bfpt_read {
+	/* The Fast Read x-y-z hardware capability in params->hwcaps.mask. */
+	u32			hwcaps;
+
+	/*
+	 * The <supported_bit> bit in <supported_dword> BFPT DWORD tells us
+	 * whether the Fast Read x-y-z command is supported.
+	 */
+	u32			supported_dword;
+	u32			supported_bit;
+
+	/*
+	 * The half-word at offset <setting_shift> in <setting_dword> BFPT DWORD
+	 * encodes the op code, the number of mode clocks and the number of wait
+	 * states to be used by Fast Read x-y-z command.
+	 */
+	u32			settings_dword;
+	u32			settings_shift;
+
+	/* The SPI protocol for this Fast Read x-y-z command. */
+	enum spi_nor_protocol	proto;
+};
+
+struct sfdp_bfpt_erase {
+	/*
+	 * The half-word at offset <shift> in DWORD <dwoard> encodes the
+	 * op code and erase sector size to be used by Sector Erase commands.
+	 */
+	u32			dword;
+	u32			shift;
+};
+
+#define SMPT_CMD_ADDRESS_LEN_MASK		GENMASK(23, 22)
+#define SMPT_CMD_ADDRESS_LEN_0			(0x0UL << 22)
+#define SMPT_CMD_ADDRESS_LEN_3			(0x1UL << 22)
+#define SMPT_CMD_ADDRESS_LEN_4			(0x2UL << 22)
+#define SMPT_CMD_ADDRESS_LEN_USE_CURRENT	(0x3UL << 22)
+
+#define SMPT_CMD_READ_DUMMY_MASK		GENMASK(19, 16)
+#define SMPT_CMD_READ_DUMMY_SHIFT		16
+#define SMPT_CMD_READ_DUMMY(_cmd) \
+	(((_cmd) & SMPT_CMD_READ_DUMMY_MASK) >> SMPT_CMD_READ_DUMMY_SHIFT)
+#define SMPT_CMD_READ_DUMMY_IS_VARIABLE		0xfUL
+
+#define SMPT_CMD_READ_DATA_MASK			GENMASK(31, 24)
+#define SMPT_CMD_READ_DATA_SHIFT		24
+#define SMPT_CMD_READ_DATA(_cmd) \
+	(((_cmd) & SMPT_CMD_READ_DATA_MASK) >> SMPT_CMD_READ_DATA_SHIFT)
+
+#define SMPT_CMD_OPCODE_MASK			GENMASK(15, 8)
+#define SMPT_CMD_OPCODE_SHIFT			8
+#define SMPT_CMD_OPCODE(_cmd) \
+	(((_cmd) & SMPT_CMD_OPCODE_MASK) >> SMPT_CMD_OPCODE_SHIFT)
+
+#define SMPT_MAP_REGION_COUNT_MASK		GENMASK(23, 16)
+#define SMPT_MAP_REGION_COUNT_SHIFT		16
+#define SMPT_MAP_REGION_COUNT(_header) \
+	((((_header) & SMPT_MAP_REGION_COUNT_MASK) >> \
+	  SMPT_MAP_REGION_COUNT_SHIFT) + 1)
+
+#define SMPT_MAP_ID_MASK			GENMASK(15, 8)
+#define SMPT_MAP_ID_SHIFT			8
+#define SMPT_MAP_ID(_header) \
+	(((_header) & SMPT_MAP_ID_MASK) >> SMPT_MAP_ID_SHIFT)
+
+#define SMPT_MAP_REGION_SIZE_MASK		GENMASK(31, 8)
+#define SMPT_MAP_REGION_SIZE_SHIFT		8
+#define SMPT_MAP_REGION_SIZE(_region) \
+	(((((_region) & SMPT_MAP_REGION_SIZE_MASK) >> \
+	   SMPT_MAP_REGION_SIZE_SHIFT) + 1) * 256)
+
+#define SMPT_MAP_REGION_ERASE_TYPE_MASK		GENMASK(3, 0)
+#define SMPT_MAP_REGION_ERASE_TYPE(_region) \
+	((_region) & SMPT_MAP_REGION_ERASE_TYPE_MASK)
+
+#define SMPT_DESC_TYPE_MAP			BIT(1)
+#define SMPT_DESC_END				BIT(0)
+
+#define SFDP_4BAIT_DWORD_MAX	2
+
+struct sfdp_4bait {
+	/* The hardware capability. */
+	u32		hwcaps;
+
+	/*
+	 * The <supported_bit> bit in DWORD1 of the 4BAIT tells us whether
+	 * the associated 4-byte address op code is supported.
+	 */
+	u32		supported_bit;
+};
+
+/**
+ * spi_nor_read_raw() - raw read of serial flash memory. read_opcode,
+ *			addr_width and read_dummy members of the struct spi_nor
+ *			should be previously
+ * set.
+ * @nor:	pointer to a 'struct spi_nor'
+ * @addr:	offset in the serial flash memory
+ * @len:	number of bytes to read
+ * @buf:	buffer where the data is copied into (dma-safe memory)
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_read_raw(struct spi_nor *nor, u32 addr, size_t len, u8 *buf)
+{
+	ssize_t ret;
+
+	while (len) {
+		ret = spi_nor_read_data(nor, addr, len, buf);
+		if (ret < 0)
+			return ret;
+		if (!ret || ret > len)
+			return -EIO;
+
+		buf += ret;
+		addr += ret;
+		len -= ret;
+	}
+	return 0;
+}
+
+/**
+ * spi_nor_read_sfdp() - read Serial Flash Discoverable Parameters.
+ * @nor:	pointer to a 'struct spi_nor'
+ * @addr:	offset in the SFDP area to start reading data from
+ * @len:	number of bytes to read
+ * @buf:	buffer where the SFDP data are copied into (dma-safe memory)
+ *
+ * Whatever the actual numbers of bytes for address and dummy cycles are
+ * for (Fast) Read commands, the Read SFDP (5Ah) instruction is always
+ * followed by a 3-byte address and 8 dummy clock cycles.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_read_sfdp(struct spi_nor *nor, u32 addr,
+			     size_t len, void *buf)
+{
+	u8 addr_width, read_opcode, read_dummy;
+	int ret;
+
+	read_opcode = nor->read_opcode;
+	addr_width = nor->addr_width;
+	read_dummy = nor->read_dummy;
+
+	nor->read_opcode = SPINOR_OP_RDSFDP;
+	nor->addr_width = 3;
+	nor->read_dummy = 8;
+
+	ret = spi_nor_read_raw(nor, addr, len, buf);
+
+	nor->read_opcode = read_opcode;
+	nor->addr_width = addr_width;
+	nor->read_dummy = read_dummy;
+
+	return ret;
+}
+
+/**
+ * spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters.
+ * @nor:	pointer to a 'struct spi_nor'
+ * @addr:	offset in the SFDP area to start reading data from
+ * @len:	number of bytes to read
+ * @buf:	buffer where the SFDP data are copied into
+ *
+ * Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not
+ * guaranteed to be dma-safe.
+ *
+ * Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp()
+ *          otherwise.
+ */
+static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr,
+					size_t len, void *buf)
+{
+	void *dma_safe_buf;
+	int ret;
+
+	dma_safe_buf = kmalloc(len, GFP_KERNEL);
+	if (!dma_safe_buf)
+		return -ENOMEM;
+
+	ret = spi_nor_read_sfdp(nor, addr, len, dma_safe_buf);
+	memcpy(buf, dma_safe_buf, len);
+	kfree(dma_safe_buf);
+
+	return ret;
+}
+
+static void
+spi_nor_set_read_settings_from_bfpt(struct spi_nor_read_command *read,
+				    u16 half,
+				    enum spi_nor_protocol proto)
+{
+	read->num_mode_clocks = (half >> 5) & 0x07;
+	read->num_wait_states = (half >> 0) & 0x1f;
+	read->opcode = (half >> 8) & 0xff;
+	read->proto = proto;
+}
+
+static const struct sfdp_bfpt_read sfdp_bfpt_reads[] = {
+	/* Fast Read 1-1-2 */
+	{
+		SNOR_HWCAPS_READ_1_1_2,
+		BFPT_DWORD(1), BIT(16),	/* Supported bit */
+		BFPT_DWORD(4), 0,	/* Settings */
+		SNOR_PROTO_1_1_2,
+	},
+
+	/* Fast Read 1-2-2 */
+	{
+		SNOR_HWCAPS_READ_1_2_2,
+		BFPT_DWORD(1), BIT(20),	/* Supported bit */
+		BFPT_DWORD(4), 16,	/* Settings */
+		SNOR_PROTO_1_2_2,
+	},
+
+	/* Fast Read 2-2-2 */
+	{
+		SNOR_HWCAPS_READ_2_2_2,
+		BFPT_DWORD(5),  BIT(0),	/* Supported bit */
+		BFPT_DWORD(6), 16,	/* Settings */
+		SNOR_PROTO_2_2_2,
+	},
+
+	/* Fast Read 1-1-4 */
+	{
+		SNOR_HWCAPS_READ_1_1_4,
+		BFPT_DWORD(1), BIT(22),	/* Supported bit */
+		BFPT_DWORD(3), 16,	/* Settings */
+		SNOR_PROTO_1_1_4,
+	},
+
+	/* Fast Read 1-4-4 */
+	{
+		SNOR_HWCAPS_READ_1_4_4,
+		BFPT_DWORD(1), BIT(21),	/* Supported bit */
+		BFPT_DWORD(3), 0,	/* Settings */
+		SNOR_PROTO_1_4_4,
+	},
+
+	/* Fast Read 4-4-4 */
+	{
+		SNOR_HWCAPS_READ_4_4_4,
+		BFPT_DWORD(5), BIT(4),	/* Supported bit */
+		BFPT_DWORD(7), 16,	/* Settings */
+		SNOR_PROTO_4_4_4,
+	},
+};
+
+static const struct sfdp_bfpt_erase sfdp_bfpt_erases[] = {
+	/* Erase Type 1 in DWORD8 bits[15:0] */
+	{BFPT_DWORD(8), 0},
+
+	/* Erase Type 2 in DWORD8 bits[31:16] */
+	{BFPT_DWORD(8), 16},
+
+	/* Erase Type 3 in DWORD9 bits[15:0] */
+	{BFPT_DWORD(9), 0},
+
+	/* Erase Type 4 in DWORD9 bits[31:16] */
+	{BFPT_DWORD(9), 16},
+};
+
+/**
+ * spi_nor_set_erase_settings_from_bfpt() - set erase type settings from BFPT
+ * @erase:	pointer to a structure that describes a SPI NOR erase type
+ * @size:	the size of the sector/block erased by the erase type
+ * @opcode:	the SPI command op code to erase the sector/block
+ * @i:		erase type index as sorted in the Basic Flash Parameter Table
+ *
+ * The supported Erase Types will be sorted at init in ascending order, with
+ * the smallest Erase Type size being the first member in the erase_type array
+ * of the spi_nor_erase_map structure. Save the Erase Type index as sorted in
+ * the Basic Flash Parameter Table since it will be used later on to
+ * synchronize with the supported Erase Types defined in SFDP optional tables.
+ */
+static void
+spi_nor_set_erase_settings_from_bfpt(struct spi_nor_erase_type *erase,
+				     u32 size, u8 opcode, u8 i)
+{
+	erase->idx = i;
+	spi_nor_set_erase_type(erase, size, opcode);
+}
+
+/**
+ * spi_nor_map_cmp_erase_type() - compare the map's erase types by size
+ * @l:	member in the left half of the map's erase_type array
+ * @r:	member in the right half of the map's erase_type array
+ *
+ * Comparison function used in the sort() call to sort in ascending order the
+ * map's erase types, the smallest erase type size being the first member in the
+ * sorted erase_type array.
+ *
+ * Return: the result of @l->size - @r->size
+ */
+static int spi_nor_map_cmp_erase_type(const void *l, const void *r)
+{
+	const struct spi_nor_erase_type *left = l, *right = r;
+
+	return left->size - right->size;
+}
+
+/**
+ * spi_nor_sort_erase_mask() - sort erase mask
+ * @map:	the erase map of the SPI NOR
+ * @erase_mask:	the erase type mask to be sorted
+ *
+ * Replicate the sort done for the map's erase types in BFPT: sort the erase
+ * mask in ascending order with the smallest erase type size starting from
+ * BIT(0) in the sorted erase mask.
+ *
+ * Return: sorted erase mask.
+ */
+static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask)
+{
+	struct spi_nor_erase_type *erase_type = map->erase_type;
+	int i;
+	u8 sorted_erase_mask = 0;
+
+	if (!erase_mask)
+		return 0;
+
+	/* Replicate the sort done for the map's erase types. */
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+		if (erase_type[i].size && erase_mask & BIT(erase_type[i].idx))
+			sorted_erase_mask |= BIT(i);
+
+	return sorted_erase_mask;
+}
+
+/**
+ * spi_nor_regions_sort_erase_types() - sort erase types in each region
+ * @map:	the erase map of the SPI NOR
+ *
+ * Function assumes that the erase types defined in the erase map are already
+ * sorted in ascending order, with the smallest erase type size being the first
+ * member in the erase_type array. It replicates the sort done for the map's
+ * erase types. Each region's erase bitmask will indicate which erase types are
+ * supported from the sorted erase types defined in the erase map.
+ * Sort the all region's erase type at init in order to speed up the process of
+ * finding the best erase command at runtime.
+ */
+static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)
+{
+	struct spi_nor_erase_region *region = map->regions;
+	u8 region_erase_mask, sorted_erase_mask;
+
+	while (region) {
+		region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK;
+
+		sorted_erase_mask = spi_nor_sort_erase_mask(map,
+							    region_erase_mask);
+
+		/* Overwrite erase mask. */
+		region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) |
+				 sorted_erase_mask;
+
+		region = spi_nor_region_next(region);
+	}
+}
+
+/**
+ * spi_nor_parse_bfpt() - read and parse the Basic Flash Parameter Table.
+ * @nor:		pointer to a 'struct spi_nor'
+ * @bfpt_header:	pointer to the 'struct sfdp_parameter_header' describing
+ *			the Basic Flash Parameter Table length and version
+ * @params:		pointer to the 'struct spi_nor_flash_parameter' to be
+ *			filled
+ *
+ * The Basic Flash Parameter Table is the main and only mandatory table as
+ * defined by the SFDP (JESD216) specification.
+ * It provides us with the total size (memory density) of the data array and
+ * the number of address bytes for Fast Read, Page Program and Sector Erase
+ * commands.
+ * For Fast READ commands, it also gives the number of mode clock cycles and
+ * wait states (regrouped in the number of dummy clock cycles) for each
+ * supported instruction op code.
+ * For Page Program, the page size is now available since JESD216 rev A, however
+ * the supported instruction op codes are still not provided.
+ * For Sector Erase commands, this table stores the supported instruction op
+ * codes and the associated sector sizes.
+ * Finally, the Quad Enable Requirements (QER) are also available since JESD216
+ * rev A. The QER bits encode the manufacturer dependent procedure to be
+ * executed to set the Quad Enable (QE) bit in some internal register of the
+ * Quad SPI memory. Indeed the QE bit, when it exists, must be set before
+ * sending any Quad SPI command to the memory. Actually, setting the QE bit
+ * tells the memory to reassign its WP# and HOLD#/RESET# pins to functions IO2
+ * and IO3 hence enabling 4 (Quad) I/O lines.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_parse_bfpt(struct spi_nor *nor,
+			      const struct sfdp_parameter_header *bfpt_header,
+			      struct spi_nor_flash_parameter *params)
+{
+	struct spi_nor_erase_map *map = &params->erase_map;
+	struct spi_nor_erase_type *erase_type = map->erase_type;
+	struct sfdp_bfpt bfpt;
+	size_t len;
+	int i, cmd, err;
+	u32 addr;
+	u16 half;
+	u8 erase_mask;
+
+	/* JESD216 Basic Flash Parameter Table length is at least 9 DWORDs. */
+	if (bfpt_header->length < BFPT_DWORD_MAX_JESD216)
+		return -EINVAL;
+
+	/* Read the Basic Flash Parameter Table. */
+	len = min_t(size_t, sizeof(bfpt),
+		    bfpt_header->length * sizeof(u32));
+	addr = SFDP_PARAM_HEADER_PTP(bfpt_header);
+	memset(&bfpt, 0, sizeof(bfpt));
+	err = spi_nor_read_sfdp_dma_unsafe(nor,  addr, len, &bfpt);
+	if (err < 0)
+		return err;
+
+	/* Fix endianness of the BFPT DWORDs. */
+	le32_to_cpu_array(bfpt.dwords, BFPT_DWORD_MAX);
+
+	/* Number of address bytes. */
+	switch (bfpt.dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) {
+	case BFPT_DWORD1_ADDRESS_BYTES_3_ONLY:
+		nor->addr_width = 3;
+		break;
+
+	case BFPT_DWORD1_ADDRESS_BYTES_4_ONLY:
+		nor->addr_width = 4;
+		break;
+
+	default:
+		break;
+	}
+
+	/* Flash Memory Density (in bits). */
+	params->size = bfpt.dwords[BFPT_DWORD(2)];
+	if (params->size & BIT(31)) {
+		params->size &= ~BIT(31);
+
+		/*
+		 * Prevent overflows on params->size. Anyway, a NOR of 2^64
+		 * bits is unlikely to exist so this error probably means
+		 * the BFPT we are reading is corrupted/wrong.
+		 */
+		if (params->size > 63)
+			return -EINVAL;
+
+		params->size = 1ULL << params->size;
+	} else {
+		params->size++;
+	}
+	params->size >>= 3; /* Convert to bytes. */
+
+	/* Fast Read settings. */
+	for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_reads); i++) {
+		const struct sfdp_bfpt_read *rd = &sfdp_bfpt_reads[i];
+		struct spi_nor_read_command *read;
+
+		if (!(bfpt.dwords[rd->supported_dword] & rd->supported_bit)) {
+			params->hwcaps.mask &= ~rd->hwcaps;
+			continue;
+		}
+
+		params->hwcaps.mask |= rd->hwcaps;
+		cmd = spi_nor_hwcaps_read2cmd(rd->hwcaps);
+		read = &params->reads[cmd];
+		half = bfpt.dwords[rd->settings_dword] >> rd->settings_shift;
+		spi_nor_set_read_settings_from_bfpt(read, half, rd->proto);
+	}
+
+	/*
+	 * Sector Erase settings. Reinitialize the uniform erase map using the
+	 * Erase Types defined in the bfpt table.
+	 */
+	erase_mask = 0;
+	memset(&params->erase_map, 0, sizeof(params->erase_map));
+	for (i = 0; i < ARRAY_SIZE(sfdp_bfpt_erases); i++) {
+		const struct sfdp_bfpt_erase *er = &sfdp_bfpt_erases[i];
+		u32 erasesize;
+		u8 opcode;
+
+		half = bfpt.dwords[er->dword] >> er->shift;
+		erasesize = half & 0xff;
+
+		/* erasesize == 0 means this Erase Type is not supported. */
+		if (!erasesize)
+			continue;
+
+		erasesize = 1U << erasesize;
+		opcode = (half >> 8) & 0xff;
+		erase_mask |= BIT(i);
+		spi_nor_set_erase_settings_from_bfpt(&erase_type[i], erasesize,
+						     opcode, i);
+	}
+	spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
+	/*
+	 * Sort all the map's Erase Types in ascending order with the smallest
+	 * erase size being the first member in the erase_type array.
+	 */
+	sort(erase_type, SNOR_ERASE_TYPE_MAX, sizeof(erase_type[0]),
+	     spi_nor_map_cmp_erase_type, NULL);
+	/*
+	 * Sort the erase types in the uniform region in order to update the
+	 * uniform_erase_type bitmask. The bitmask will be used later on when
+	 * selecting the uniform erase.
+	 */
+	spi_nor_regions_sort_erase_types(map);
+	map->uniform_erase_type = map->uniform_region.offset &
+				  SNOR_ERASE_TYPE_MASK;
+
+	/* Stop here if not JESD216 rev A or later. */
+	if (bfpt_header->length < BFPT_DWORD_MAX)
+		return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt,
+						params);
+
+	/* Page size: this field specifies 'N' so the page size = 2^N bytes. */
+	params->page_size = bfpt.dwords[BFPT_DWORD(11)];
+	params->page_size &= BFPT_DWORD11_PAGE_SIZE_MASK;
+	params->page_size >>= BFPT_DWORD11_PAGE_SIZE_SHIFT;
+	params->page_size = 1U << params->page_size;
+
+	/* Quad Enable Requirements. */
+	switch (bfpt.dwords[BFPT_DWORD(15)] & BFPT_DWORD15_QER_MASK) {
+	case BFPT_DWORD15_QER_NONE:
+		params->quad_enable = NULL;
+		break;
+
+	case BFPT_DWORD15_QER_SR2_BIT1_BUGGY:
+		/*
+		 * Writing only one byte to the Status Register has the
+		 * side-effect of clearing Status Register 2.
+		 */
+	case BFPT_DWORD15_QER_SR2_BIT1_NO_RD:
+		/*
+		 * Read Configuration Register (35h) instruction is not
+		 * supported.
+		 */
+		nor->flags |= SNOR_F_HAS_16BIT_SR | SNOR_F_NO_READ_CR;
+		params->quad_enable = spi_nor_sr2_bit1_quad_enable;
+		break;
+
+	case BFPT_DWORD15_QER_SR1_BIT6:
+		nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+		params->quad_enable = spi_nor_sr1_bit6_quad_enable;
+		break;
+
+	case BFPT_DWORD15_QER_SR2_BIT7:
+		nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+		params->quad_enable = spi_nor_sr2_bit7_quad_enable;
+		break;
+
+	case BFPT_DWORD15_QER_SR2_BIT1:
+		/*
+		 * JESD216 rev B or later does not specify if writing only one
+		 * byte to the Status Register clears or not the Status
+		 * Register 2, so let's be cautious and keep the default
+		 * assumption of a 16-bit Write Status (01h) command.
+		 */
+		nor->flags |= SNOR_F_HAS_16BIT_SR;
+
+		params->quad_enable = spi_nor_sr2_bit1_quad_enable;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return spi_nor_post_bfpt_fixups(nor, bfpt_header, &bfpt, params);
+}
+
+/**
+ * spi_nor_smpt_addr_width() - return the address width used in the
+ *			       configuration detection command.
+ * @nor:	pointer to a 'struct spi_nor'
+ * @settings:	configuration detection command descriptor, dword1
+ */
+static u8 spi_nor_smpt_addr_width(const struct spi_nor *nor, const u32 settings)
+{
+	switch (settings & SMPT_CMD_ADDRESS_LEN_MASK) {
+	case SMPT_CMD_ADDRESS_LEN_0:
+		return 0;
+	case SMPT_CMD_ADDRESS_LEN_3:
+		return 3;
+	case SMPT_CMD_ADDRESS_LEN_4:
+		return 4;
+	case SMPT_CMD_ADDRESS_LEN_USE_CURRENT:
+		/* fall through */
+	default:
+		return nor->addr_width;
+	}
+}
+
+/**
+ * spi_nor_smpt_read_dummy() - return the configuration detection command read
+ *			       latency, in clock cycles.
+ * @nor:	pointer to a 'struct spi_nor'
+ * @settings:	configuration detection command descriptor, dword1
+ *
+ * Return: the number of dummy cycles for an SMPT read
+ */
+static u8 spi_nor_smpt_read_dummy(const struct spi_nor *nor, const u32 settings)
+{
+	u8 read_dummy = SMPT_CMD_READ_DUMMY(settings);
+
+	if (read_dummy == SMPT_CMD_READ_DUMMY_IS_VARIABLE)
+		return nor->read_dummy;
+	return read_dummy;
+}
+
+/**
+ * spi_nor_get_map_in_use() - get the configuration map in use
+ * @nor:	pointer to a 'struct spi_nor'
+ * @smpt:	pointer to the sector map parameter table
+ * @smpt_len:	sector map parameter table length
+ *
+ * Return: pointer to the map in use, ERR_PTR(-errno) otherwise.
+ */
+static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
+					 u8 smpt_len)
+{
+	const u32 *ret;
+	u8 *buf;
+	u32 addr;
+	int err;
+	u8 i;
+	u8 addr_width, read_opcode, read_dummy;
+	u8 read_data_mask, map_id;
+
+	/* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */
+	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	addr_width = nor->addr_width;
+	read_dummy = nor->read_dummy;
+	read_opcode = nor->read_opcode;
+
+	map_id = 0;
+	/* Determine if there are any optional Detection Command Descriptors */
+	for (i = 0; i < smpt_len; i += 2) {
+		if (smpt[i] & SMPT_DESC_TYPE_MAP)
+			break;
+
+		read_data_mask = SMPT_CMD_READ_DATA(smpt[i]);
+		nor->addr_width = spi_nor_smpt_addr_width(nor, smpt[i]);
+		nor->read_dummy = spi_nor_smpt_read_dummy(nor, smpt[i]);
+		nor->read_opcode = SMPT_CMD_OPCODE(smpt[i]);
+		addr = smpt[i + 1];
+
+		err = spi_nor_read_raw(nor, addr, 1, buf);
+		if (err) {
+			ret = ERR_PTR(err);
+			goto out;
+		}
+
+		/*
+		 * Build an index value that is used to select the Sector Map
+		 * Configuration that is currently in use.
+		 */
+		map_id = map_id << 1 | !!(*buf & read_data_mask);
+	}
+
+	/*
+	 * If command descriptors are provided, they always precede map
+	 * descriptors in the table. There is no need to start the iteration
+	 * over smpt array all over again.
+	 *
+	 * Find the matching configuration map.
+	 */
+	ret = ERR_PTR(-EINVAL);
+	while (i < smpt_len) {
+		if (SMPT_MAP_ID(smpt[i]) == map_id) {
+			ret = smpt + i;
+			break;
+		}
+
+		/*
+		 * If there are no more configuration map descriptors and no
+		 * configuration ID matched the configuration identifier, the
+		 * sector address map is unknown.
+		 */
+		if (smpt[i] & SMPT_DESC_END)
+			break;
+
+		/* increment the table index to the next map */
+		i += SMPT_MAP_REGION_COUNT(smpt[i]) + 1;
+	}
+
+	/* fall through */
+out:
+	kfree(buf);
+	nor->addr_width = addr_width;
+	nor->read_dummy = read_dummy;
+	nor->read_opcode = read_opcode;
+	return ret;
+}
+
+/**
+ * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid
+ * @region:	pointer to a structure that describes a SPI NOR erase region
+ * @erase:	pointer to a structure that describes a SPI NOR erase type
+ * @erase_type:	erase type bitmask
+ */
+static void
+spi_nor_region_check_overlay(struct spi_nor_erase_region *region,
+			     const struct spi_nor_erase_type *erase,
+			     const u8 erase_type)
+{
+	int i;
+
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
+		if (!(erase_type & BIT(i)))
+			continue;
+		if (region->size & erase[i].size_mask) {
+			spi_nor_region_mark_overlay(region);
+			return;
+		}
+	}
+}
+
+/**
+ * spi_nor_init_non_uniform_erase_map() - initialize the non-uniform erase map
+ * @nor:	pointer to a 'struct spi_nor'
+ * @params:     pointer to a duplicate 'struct spi_nor_flash_parameter' that is
+ *              used for storing SFDP parsed data
+ * @smpt:	pointer to the sector map parameter table
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int
+spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
+				   struct spi_nor_flash_parameter *params,
+				   const u32 *smpt)
+{
+	struct spi_nor_erase_map *map = &params->erase_map;
+	struct spi_nor_erase_type *erase = map->erase_type;
+	struct spi_nor_erase_region *region;
+	u64 offset;
+	u32 region_count;
+	int i, j;
+	u8 uniform_erase_type, save_uniform_erase_type;
+	u8 erase_type, regions_erase_type;
+
+	region_count = SMPT_MAP_REGION_COUNT(*smpt);
+	/*
+	 * The regions will be freed when the driver detaches from the
+	 * device.
+	 */
+	region = devm_kcalloc(nor->dev, region_count, sizeof(*region),
+			      GFP_KERNEL);
+	if (!region)
+		return -ENOMEM;
+	map->regions = region;
+
+	uniform_erase_type = 0xff;
+	regions_erase_type = 0;
+	offset = 0;
+	/* Populate regions. */
+	for (i = 0; i < region_count; i++) {
+		j = i + 1; /* index for the region dword */
+		region[i].size = SMPT_MAP_REGION_SIZE(smpt[j]);
+		erase_type = SMPT_MAP_REGION_ERASE_TYPE(smpt[j]);
+		region[i].offset = offset | erase_type;
+
+		spi_nor_region_check_overlay(&region[i], erase, erase_type);
+
+		/*
+		 * Save the erase types that are supported in all regions and
+		 * can erase the entire flash memory.
+		 */
+		uniform_erase_type &= erase_type;
+
+		/*
+		 * regions_erase_type mask will indicate all the erase types
+		 * supported in this configuration map.
+		 */
+		regions_erase_type |= erase_type;
+
+		offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
+			 region[i].size;
+	}
+
+	save_uniform_erase_type = map->uniform_erase_type;
+	map->uniform_erase_type = spi_nor_sort_erase_mask(map,
+							  uniform_erase_type);
+
+	if (!regions_erase_type) {
+		/*
+		 * Roll back to the previous uniform_erase_type mask, SMPT is
+		 * broken.
+		 */
+		map->uniform_erase_type = save_uniform_erase_type;
+		return -EINVAL;
+	}
+
+	/*
+	 * BFPT advertises all the erase types supported by all the possible
+	 * map configurations. Mask out the erase types that are not supported
+	 * by the current map configuration.
+	 */
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+		if (!(regions_erase_type & BIT(erase[i].idx)))
+			spi_nor_set_erase_type(&erase[i], 0, 0xFF);
+
+	spi_nor_region_mark_end(&region[i - 1]);
+
+	return 0;
+}
+
+/**
+ * spi_nor_parse_smpt() - parse Sector Map Parameter Table
+ * @nor:		pointer to a 'struct spi_nor'
+ * @smpt_header:	sector map parameter table header
+ * @params:		pointer to a duplicate 'struct spi_nor_flash_parameter'
+ *                      that is used for storing SFDP parsed data
+ *
+ * This table is optional, but when available, we parse it to identify the
+ * location and size of sectors within the main data array of the flash memory
+ * device and to identify which Erase Types are supported by each sector.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_parse_smpt(struct spi_nor *nor,
+			      const struct sfdp_parameter_header *smpt_header,
+			      struct spi_nor_flash_parameter *params)
+{
+	const u32 *sector_map;
+	u32 *smpt;
+	size_t len;
+	u32 addr;
+	int ret;
+
+	/* Read the Sector Map Parameter Table. */
+	len = smpt_header->length * sizeof(*smpt);
+	smpt = kmalloc(len, GFP_KERNEL);
+	if (!smpt)
+		return -ENOMEM;
+
+	addr = SFDP_PARAM_HEADER_PTP(smpt_header);
+	ret = spi_nor_read_sfdp(nor, addr, len, smpt);
+	if (ret)
+		goto out;
+
+	/* Fix endianness of the SMPT DWORDs. */
+	le32_to_cpu_array(smpt, smpt_header->length);
+
+	sector_map = spi_nor_get_map_in_use(nor, smpt, smpt_header->length);
+	if (IS_ERR(sector_map)) {
+		ret = PTR_ERR(sector_map);
+		goto out;
+	}
+
+	ret = spi_nor_init_non_uniform_erase_map(nor, params, sector_map);
+	if (ret)
+		goto out;
+
+	spi_nor_regions_sort_erase_types(&params->erase_map);
+	/* fall through */
+out:
+	kfree(smpt);
+	return ret;
+}
+
+/**
+ * spi_nor_parse_4bait() - parse the 4-Byte Address Instruction Table
+ * @nor:		pointer to a 'struct spi_nor'.
+ * @param_header:	pointer to the 'struct sfdp_parameter_header' describing
+ *			the 4-Byte Address Instruction Table length and version.
+ * @params:		pointer to the 'struct spi_nor_flash_parameter' to be.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int spi_nor_parse_4bait(struct spi_nor *nor,
+			       const struct sfdp_parameter_header *param_header,
+			       struct spi_nor_flash_parameter *params)
+{
+	static const struct sfdp_4bait reads[] = {
+		{ SNOR_HWCAPS_READ,		BIT(0) },
+		{ SNOR_HWCAPS_READ_FAST,	BIT(1) },
+		{ SNOR_HWCAPS_READ_1_1_2,	BIT(2) },
+		{ SNOR_HWCAPS_READ_1_2_2,	BIT(3) },
+		{ SNOR_HWCAPS_READ_1_1_4,	BIT(4) },
+		{ SNOR_HWCAPS_READ_1_4_4,	BIT(5) },
+		{ SNOR_HWCAPS_READ_1_1_1_DTR,	BIT(13) },
+		{ SNOR_HWCAPS_READ_1_2_2_DTR,	BIT(14) },
+		{ SNOR_HWCAPS_READ_1_4_4_DTR,	BIT(15) },
+	};
+	static const struct sfdp_4bait programs[] = {
+		{ SNOR_HWCAPS_PP,		BIT(6) },
+		{ SNOR_HWCAPS_PP_1_1_4,		BIT(7) },
+		{ SNOR_HWCAPS_PP_1_4_4,		BIT(8) },
+	};
+	static const struct sfdp_4bait erases[SNOR_ERASE_TYPE_MAX] = {
+		{ 0u /* not used */,		BIT(9) },
+		{ 0u /* not used */,		BIT(10) },
+		{ 0u /* not used */,		BIT(11) },
+		{ 0u /* not used */,		BIT(12) },
+	};
+	struct spi_nor_pp_command *params_pp = params->page_programs;
+	struct spi_nor_erase_map *map = &params->erase_map;
+	struct spi_nor_erase_type *erase_type = map->erase_type;
+	u32 *dwords;
+	size_t len;
+	u32 addr, discard_hwcaps, read_hwcaps, pp_hwcaps, erase_mask;
+	int i, ret;
+
+	if (param_header->major != SFDP_JESD216_MAJOR ||
+	    param_header->length < SFDP_4BAIT_DWORD_MAX)
+		return -EINVAL;
+
+	/* Read the 4-byte Address Instruction Table. */
+	len = sizeof(*dwords) * SFDP_4BAIT_DWORD_MAX;
+
+	/* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */
+	dwords = kmalloc(len, GFP_KERNEL);
+	if (!dwords)
+		return -ENOMEM;
+
+	addr = SFDP_PARAM_HEADER_PTP(param_header);
+	ret = spi_nor_read_sfdp(nor, addr, len, dwords);
+	if (ret)
+		goto out;
+
+	/* Fix endianness of the 4BAIT DWORDs. */
+	le32_to_cpu_array(dwords, SFDP_4BAIT_DWORD_MAX);
+
+	/*
+	 * Compute the subset of (Fast) Read commands for which the 4-byte
+	 * version is supported.
+	 */
+	discard_hwcaps = 0;
+	read_hwcaps = 0;
+	for (i = 0; i < ARRAY_SIZE(reads); i++) {
+		const struct sfdp_4bait *read = &reads[i];
+
+		discard_hwcaps |= read->hwcaps;
+		if ((params->hwcaps.mask & read->hwcaps) &&
+		    (dwords[0] & read->supported_bit))
+			read_hwcaps |= read->hwcaps;
+	}
+
+	/*
+	 * Compute the subset of Page Program commands for which the 4-byte
+	 * version is supported.
+	 */
+	pp_hwcaps = 0;
+	for (i = 0; i < ARRAY_SIZE(programs); i++) {
+		const struct sfdp_4bait *program = &programs[i];
+
+		/*
+		 * The 4 Byte Address Instruction (Optional) Table is the only
+		 * SFDP table that indicates support for Page Program Commands.
+		 * Bypass the params->hwcaps.mask and consider 4BAIT the biggest
+		 * authority for specifying Page Program support.
+		 */
+		discard_hwcaps |= program->hwcaps;
+		if (dwords[0] & program->supported_bit)
+			pp_hwcaps |= program->hwcaps;
+	}
+
+	/*
+	 * Compute the subset of Sector Erase commands for which the 4-byte
+	 * version is supported.
+	 */
+	erase_mask = 0;
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
+		const struct sfdp_4bait *erase = &erases[i];
+
+		if (dwords[0] & erase->supported_bit)
+			erase_mask |= BIT(i);
+	}
+
+	/* Replicate the sort done for the map's erase types in BFPT. */
+	erase_mask = spi_nor_sort_erase_mask(map, erase_mask);
+
+	/*
+	 * We need at least one 4-byte op code per read, program and erase
+	 * operation; the .read(), .write() and .erase() hooks share the
+	 * nor->addr_width value.
+	 */
+	if (!read_hwcaps || !pp_hwcaps || !erase_mask)
+		goto out;
+
+	/*
+	 * Discard all operations from the 4-byte instruction set which are
+	 * not supported by this memory.
+	 */
+	params->hwcaps.mask &= ~discard_hwcaps;
+	params->hwcaps.mask |= (read_hwcaps | pp_hwcaps);
+
+	/* Use the 4-byte address instruction set. */
+	for (i = 0; i < SNOR_CMD_READ_MAX; i++) {
+		struct spi_nor_read_command *read_cmd = &params->reads[i];
+
+		read_cmd->opcode = spi_nor_convert_3to4_read(read_cmd->opcode);
+	}
+
+	/* 4BAIT is the only SFDP table that indicates page program support. */
+	if (pp_hwcaps & SNOR_HWCAPS_PP)
+		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP],
+					SPINOR_OP_PP_4B, SNOR_PROTO_1_1_1);
+	if (pp_hwcaps & SNOR_HWCAPS_PP_1_1_4)
+		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP_1_1_4],
+					SPINOR_OP_PP_1_1_4_4B,
+					SNOR_PROTO_1_1_4);
+	if (pp_hwcaps & SNOR_HWCAPS_PP_1_4_4)
+		spi_nor_set_pp_settings(&params_pp[SNOR_CMD_PP_1_4_4],
+					SPINOR_OP_PP_1_4_4_4B,
+					SNOR_PROTO_1_4_4);
+
+	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) {
+		if (erase_mask & BIT(i))
+			erase_type[i].opcode = (dwords[1] >>
+						erase_type[i].idx * 8) & 0xFF;
+		else
+			spi_nor_set_erase_type(&erase_type[i], 0u, 0xFF);
+	}
+
+	/*
+	 * We set SNOR_F_HAS_4BAIT in order to skip spi_nor_set_4byte_opcodes()
+	 * later because we already did the conversion to 4byte opcodes. Also,
+	 * this latest function implements a legacy quirk for the erase size of
+	 * Spansion memory. However this quirk is no longer needed with new
+	 * SFDP compliant memories.
+	 */
+	nor->addr_width = 4;
+	nor->flags |= SNOR_F_4B_OPCODES | SNOR_F_HAS_4BAIT;
+
+	/* fall through */
+out:
+	kfree(dwords);
+	return ret;
+}
+
+/**
+ * spi_nor_parse_sfdp() - parse the Serial Flash Discoverable Parameters.
+ * @nor:		pointer to a 'struct spi_nor'
+ * @params:		pointer to the 'struct spi_nor_flash_parameter' to be
+ *			filled
+ *
+ * The Serial Flash Discoverable Parameters are described by the JEDEC JESD216
+ * specification. This is a standard which tends to supported by almost all
+ * (Q)SPI memory manufacturers. Those hard-coded tables allow us to learn at
+ * runtime the main parameters needed to perform basic SPI flash operations such
+ * as Fast Read, Page Program or Sector Erase commands.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_parse_sfdp(struct spi_nor *nor,
+		       struct spi_nor_flash_parameter *params)
+{
+	const struct sfdp_parameter_header *param_header, *bfpt_header;
+	struct sfdp_parameter_header *param_headers = NULL;
+	struct sfdp_header header;
+	struct device *dev = nor->dev;
+	size_t psize;
+	int i, err;
+
+	/* Get the SFDP header. */
+	err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header);
+	if (err < 0)
+		return err;
+
+	/* Check the SFDP header version. */
+	if (le32_to_cpu(header.signature) != SFDP_SIGNATURE ||
+	    header.major != SFDP_JESD216_MAJOR)
+		return -EINVAL;
+
+	/*
+	 * Verify that the first and only mandatory parameter header is a
+	 * Basic Flash Parameter Table header as specified in JESD216.
+	 */
+	bfpt_header = &header.bfpt_header;
+	if (SFDP_PARAM_HEADER_ID(bfpt_header) != SFDP_BFPT_ID ||
+	    bfpt_header->major != SFDP_JESD216_MAJOR)
+		return -EINVAL;
+
+	/*
+	 * Allocate memory then read all parameter headers with a single
+	 * Read SFDP command. These parameter headers will actually be parsed
+	 * twice: a first time to get the latest revision of the basic flash
+	 * parameter table, then a second time to handle the supported optional
+	 * tables.
+	 * Hence we read the parameter headers once for all to reduce the
+	 * processing time. Also we use kmalloc() instead of devm_kmalloc()
+	 * because we don't need to keep these parameter headers: the allocated
+	 * memory is always released with kfree() before exiting this function.
+	 */
+	if (header.nph) {
+		psize = header.nph * sizeof(*param_headers);
+
+		param_headers = kmalloc(psize, GFP_KERNEL);
+		if (!param_headers)
+			return -ENOMEM;
+
+		err = spi_nor_read_sfdp(nor, sizeof(header),
+					psize, param_headers);
+		if (err < 0) {
+			dev_dbg(dev, "failed to read SFDP parameter headers\n");
+			goto exit;
+		}
+	}
+
+	/*
+	 * Check other parameter headers to get the latest revision of
+	 * the basic flash parameter table.
+	 */
+	for (i = 0; i < header.nph; i++) {
+		param_header = &param_headers[i];
+
+		if (SFDP_PARAM_HEADER_ID(param_header) == SFDP_BFPT_ID &&
+		    param_header->major == SFDP_JESD216_MAJOR &&
+		    (param_header->minor > bfpt_header->minor ||
+		     (param_header->minor == bfpt_header->minor &&
+		      param_header->length > bfpt_header->length)))
+			bfpt_header = param_header;
+	}
+
+	err = spi_nor_parse_bfpt(nor, bfpt_header, params);
+	if (err)
+		goto exit;
+
+	/* Parse optional parameter tables. */
+	for (i = 0; i < header.nph; i++) {
+		param_header = &param_headers[i];
+
+		switch (SFDP_PARAM_HEADER_ID(param_header)) {
+		case SFDP_SECTOR_MAP_ID:
+			err = spi_nor_parse_smpt(nor, param_header, params);
+			break;
+
+		case SFDP_4BAIT_ID:
+			err = spi_nor_parse_4bait(nor, param_header, params);
+			break;
+
+		default:
+			break;
+		}
+
+		if (err) {
+			dev_warn(dev, "Failed to parse optional parameter table: %04x\n",
+				 SFDP_PARAM_HEADER_ID(param_header));
+			/*
+			 * Let's not drop all information we extracted so far
+			 * if optional table parsers fail. In case of failing,
+			 * each optional parser is responsible to roll back to
+			 * the previously known spi_nor data.
+			 */
+			err = 0;
+		}
+	}
+
+exit:
+	kfree(param_headers);
+	return err;
+}
+
diff --git a/drivers/mtd/spi-nor/sfdp.h b/drivers/mtd/spi-nor/sfdp.h
new file mode 100644
index 000000000000..e0a8ded04890
--- /dev/null
+++ b/drivers/mtd/spi-nor/sfdp.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#ifndef __LINUX_MTD_SFDP_H
+#define __LINUX_MTD_SFDP_H
+
+/* Basic Flash Parameter Table */
+
+/*
+ * JESD216 rev B defines a Basic Flash Parameter Table of 16 DWORDs.
+ * They are indexed from 1 but C arrays are indexed from 0.
+ */
+#define BFPT_DWORD(i)		((i) - 1)
+#define BFPT_DWORD_MAX		16
+
+struct sfdp_bfpt {
+	u32	dwords[BFPT_DWORD_MAX];
+};
+
+/* The first version of JESD216 defined only 9 DWORDs. */
+#define BFPT_DWORD_MAX_JESD216			9
+
+/* 1st DWORD. */
+#define BFPT_DWORD1_FAST_READ_1_1_2		BIT(16)
+#define BFPT_DWORD1_ADDRESS_BYTES_MASK		GENMASK(18, 17)
+#define BFPT_DWORD1_ADDRESS_BYTES_3_ONLY	(0x0UL << 17)
+#define BFPT_DWORD1_ADDRESS_BYTES_3_OR_4	(0x1UL << 17)
+#define BFPT_DWORD1_ADDRESS_BYTES_4_ONLY	(0x2UL << 17)
+#define BFPT_DWORD1_DTR				BIT(19)
+#define BFPT_DWORD1_FAST_READ_1_2_2		BIT(20)
+#define BFPT_DWORD1_FAST_READ_1_4_4		BIT(21)
+#define BFPT_DWORD1_FAST_READ_1_1_4		BIT(22)
+
+/* 5th DWORD. */
+#define BFPT_DWORD5_FAST_READ_2_2_2		BIT(0)
+#define BFPT_DWORD5_FAST_READ_4_4_4		BIT(4)
+
+/* 11th DWORD. */
+#define BFPT_DWORD11_PAGE_SIZE_SHIFT		4
+#define BFPT_DWORD11_PAGE_SIZE_MASK		GENMASK(7, 4)
+
+/* 15th DWORD. */
+
+/*
+ * (from JESD216 rev B)
+ * Quad Enable Requirements (QER):
+ * - 000b: Device does not have a QE bit. Device detects 1-1-4 and 1-4-4
+ *         reads based on instruction. DQ3/HOLD# functions are hold during
+ *         instruction phase.
+ * - 001b: QE is bit 1 of status register 2. It is set via Write Status with
+ *         two data bytes where bit 1 of the second byte is one.
+ *         [...]
+ *         Writing only one byte to the status register has the side-effect of
+ *         clearing status register 2, including the QE bit. The 100b code is
+ *         used if writing one byte to the status register does not modify
+ *         status register 2.
+ * - 010b: QE is bit 6 of status register 1. It is set via Write Status with
+ *         one data byte where bit 6 is one.
+ *         [...]
+ * - 011b: QE is bit 7 of status register 2. It is set via Write status
+ *         register 2 instruction 3Eh with one data byte where bit 7 is one.
+ *         [...]
+ *         The status register 2 is read using instruction 3Fh.
+ * - 100b: QE is bit 1 of status register 2. It is set via Write Status with
+ *         two data bytes where bit 1 of the second byte is one.
+ *         [...]
+ *         In contrast to the 001b code, writing one byte to the status
+ *         register does not modify status register 2.
+ * - 101b: QE is bit 1 of status register 2. Status register 1 is read using
+ *         Read Status instruction 05h. Status register2 is read using
+ *         instruction 35h. QE is set via Write Status instruction 01h with
+ *         two data bytes where bit 1 of the second byte is one.
+ *         [...]
+ */
+#define BFPT_DWORD15_QER_MASK			GENMASK(22, 20)
+#define BFPT_DWORD15_QER_NONE			(0x0UL << 20) /* Micron */
+#define BFPT_DWORD15_QER_SR2_BIT1_BUGGY		(0x1UL << 20)
+#define BFPT_DWORD15_QER_SR1_BIT6		(0x2UL << 20) /* Macronix */
+#define BFPT_DWORD15_QER_SR2_BIT7		(0x3UL << 20)
+#define BFPT_DWORD15_QER_SR2_BIT1_NO_RD		(0x4UL << 20)
+#define BFPT_DWORD15_QER_SR2_BIT1		(0x5UL << 20) /* Spansion */
+
+struct sfdp_parameter_header {
+	u8		id_lsb;
+	u8		minor;
+	u8		major;
+	u8		length; /* in double words */
+	u8		parameter_table_pointer[3]; /* byte address */
+	u8		id_msb;
+};
+
+int spi_nor_parse_sfdp(struct spi_nor *nor,
+		       struct spi_nor_flash_parameter *params);
+
+#endif /* __LINUX_MTD_SFDP_H */
-- 
2.23.0

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

* [PATCH 04/23] mtd: spi-nor: Expose stuctures and functions to manufacturer drivers
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (2 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 03/23] mtd: spi-nor: Move SFDP logic out of the core Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-13  6:38   ` Vignesh Raghavendra
  2020-03-02 18:07 ` [PATCH 05/23] mtd: spi-nor: Add the concept of SPI NOR manufacturer driver Tudor.Ambarus
                   ` (19 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Expose the flash_info struct and the generic set_4byte() implementations.
Some manufacturers rely on the generic set_4byte() implementations.
Remove the static specifier and expose their prototypes in core.h.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/core.c | 171 +++----------------------------------
 drivers/mtd/spi-nor/core.h | 159 ++++++++++++++++++++++++++++++++++
 2 files changed, 170 insertions(+), 160 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 1edcb53c4df3..16cf9d4b1a73 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -38,102 +38,8 @@
  */
 #define CHIP_ERASE_2MB_READY_WAIT_JIFFIES	(40UL * HZ)
 
-#define SPI_NOR_MAX_ID_LEN	6
 #define SPI_NOR_MAX_ADDR_WIDTH	4
 
-/**
- * struct spi_nor_fixups - SPI NOR fixup hooks
- * @default_init: called after default flash parameters init. Used to tweak
- *                flash parameters when information provided by the flash_info
- *                table is incomplete or wrong.
- * @post_bfpt: called after the BFPT table has been parsed
- * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
- *             that do not support RDSFDP). Typically used to tweak various
- *             parameters that could not be extracted by other means (i.e.
- *             when information provided by the SFDP/flash_info tables are
- *             incomplete or wrong).
- *
- * Those hooks can be used to tweak the SPI NOR configuration when the SFDP
- * table is broken or not available.
- */
-struct spi_nor_fixups {
-	void (*default_init)(struct spi_nor *nor);
-	int (*post_bfpt)(struct spi_nor *nor,
-			 const struct sfdp_parameter_header *bfpt_header,
-			 const struct sfdp_bfpt *bfpt,
-			 struct spi_nor_flash_parameter *params);
-	void (*post_sfdp)(struct spi_nor *nor);
-};
-
-struct flash_info {
-	char		*name;
-
-	/*
-	 * This array stores the ID bytes.
-	 * The first three bytes are the JEDIC ID.
-	 * JEDEC ID zero means "no ID" (mostly older chips).
-	 */
-	u8		id[SPI_NOR_MAX_ID_LEN];
-	u8		id_len;
-
-	/* The size listed here is what works with SPINOR_OP_SE, which isn't
-	 * necessarily called a "sector" by the vendor.
-	 */
-	unsigned	sector_size;
-	u16		n_sectors;
-
-	u16		page_size;
-	u16		addr_width;
-
-	u32		flags;
-#define SECT_4K			BIT(0)	/* SPINOR_OP_BE_4K works uniformly */
-#define SPI_NOR_NO_ERASE	BIT(1)	/* No erase command needed */
-#define SST_WRITE		BIT(2)	/* use SST byte programming */
-#define SPI_NOR_NO_FR		BIT(3)	/* Can't do fastread */
-#define SECT_4K_PMC		BIT(4)	/* SPINOR_OP_BE_4K_PMC works uniformly */
-#define SPI_NOR_DUAL_READ	BIT(5)	/* Flash supports Dual Read */
-#define SPI_NOR_QUAD_READ	BIT(6)	/* Flash supports Quad Read */
-#define USE_FSR			BIT(7)	/* use flag status register */
-#define SPI_NOR_HAS_LOCK	BIT(8)	/* Flash supports lock/unlock via SR */
-#define SPI_NOR_HAS_TB		BIT(9)	/*
-					 * Flash SR has Top/Bottom (TB) protect
-					 * bit. Must be used with
-					 * SPI_NOR_HAS_LOCK.
-					 */
-#define SPI_NOR_XSR_RDY		BIT(10)	/*
-					 * S3AN flashes have specific opcode to
-					 * read the status register.
-					 * Flags SPI_NOR_XSR_RDY and SPI_S3AN
-					 * use the same bit as one implies the
-					 * other, but we will get rid of
-					 * SPI_S3AN soon.
-					 */
-#define	SPI_S3AN		BIT(10)	/*
-					 * Xilinx Spartan 3AN In-System Flash
-					 * (MFR cannot be used for probing
-					 * because it has the same value as
-					 * ATMEL flashes)
-					 */
-#define SPI_NOR_4B_OPCODES	BIT(11)	/*
-					 * Use dedicated 4byte address op codes
-					 * to support memory size above 128Mib.
-					 */
-#define NO_CHIP_ERASE		BIT(12) /* Chip does not support chip erase */
-#define SPI_NOR_SKIP_SFDP	BIT(13)	/* Skip parsing of SFDP tables */
-#define USE_CLSR		BIT(14)	/* use CLSR command */
-#define SPI_NOR_OCTAL_READ	BIT(15)	/* Flash supports Octal Read */
-#define SPI_NOR_TB_SR_BIT6	BIT(16)	/*
-					 * Top/Bottom (TB) is bit 6 of
-					 * status register. Must be used with
-					 * SPI_NOR_HAS_TB.
-					 */
-
-	/* Part specific fixup hooks. */
-	const struct spi_nor_fixups *fixups;
-};
-
-#define JEDEC_MFR(info)	((info)->id[0])
-
 /**
  * spi_nor_spimem_bounce() - check if a bounce buffer is needed for the data
  *                           transfer
@@ -295,8 +201,8 @@ static ssize_t spi_nor_spimem_write_data(struct spi_nor *nor, loff_t to,
  *
  * Return: number of bytes written successfully, -errno otherwise
  */
-static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
-				  const u8 *buf)
+ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
+			   const u8 *buf)
 {
 	if (nor->spimem)
 		return spi_nor_spimem_write_data(nor, to, len, buf);
@@ -310,7 +216,7 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_write_enable(struct spi_nor *nor)
+int spi_nor_write_enable(struct spi_nor *nor)
 {
 	int ret;
 
@@ -339,7 +245,7 @@ static int spi_nor_write_enable(struct spi_nor *nor)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_write_disable(struct spi_nor *nor)
+int spi_nor_write_disable(struct spi_nor *nor)
 {
 	int ret;
 
@@ -464,7 +370,7 @@ static int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable)
+int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable)
 {
 	int ret;
 
@@ -501,7 +407,7 @@ static int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_en4_ex4_wen_set_4byte(struct spi_nor *nor, bool enable)
+int spi_nor_en4_ex4_wen_set_4byte(struct spi_nor *nor, bool enable)
 {
 	int ret;
 
@@ -556,7 +462,7 @@ static int spansion_set_4byte(struct spi_nor *nor, bool enable)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
+int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
 {
 	int ret;
 
@@ -621,7 +527,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable)
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr)
+int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr)
 {
 	int ret;
 
@@ -834,7 +740,7 @@ static int spi_nor_wait_till_ready_with_timeout(struct spi_nor *nor,
  *
  * Return: 0 on success, -errno otherwise.
  */
-static int spi_nor_wait_till_ready(struct spi_nor *nor)
+int spi_nor_wait_till_ready(struct spi_nor *nor)
 {
 	return spi_nor_wait_till_ready_with_timeout(nor,
 						    DEFAULT_READY_WAIT_JIFFIES);
@@ -1142,11 +1048,6 @@ static int spi_nor_erase_chip(struct spi_nor *nor)
 	return ret;
 }
 
-static struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
-{
-	return mtd->priv;
-}
-
 static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size)
 {
 	size_t i;
@@ -1225,7 +1126,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
 	}
 }
 
-static int spi_nor_lock_and_prep(struct spi_nor *nor)
+int spi_nor_lock_and_prep(struct spi_nor *nor)
 {
 	int ret = 0;
 
@@ -1241,7 +1142,7 @@ static int spi_nor_lock_and_prep(struct spi_nor *nor)
 	return ret;
 }
 
-static void spi_nor_unlock_and_unprep(struct spi_nor *nor)
+void spi_nor_unlock_and_unprep(struct spi_nor *nor)
 {
 	if (nor->controller_ops && nor->controller_ops->unprepare)
 		nor->controller_ops->unprepare(nor);
@@ -2104,56 +2005,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
 	return 0;
 }
 
-/* Used when the "_ext_id" is two bytes at most */
-#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
-		.id = {							\
-			((_jedec_id) >> 16) & 0xff,			\
-			((_jedec_id) >> 8) & 0xff,			\
-			(_jedec_id) & 0xff,				\
-			((_ext_id) >> 8) & 0xff,			\
-			(_ext_id) & 0xff,				\
-			},						\
-		.id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),	\
-		.sector_size = (_sector_size),				\
-		.n_sectors = (_n_sectors),				\
-		.page_size = 256,					\
-		.flags = (_flags),
-
-#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
-		.id = {							\
-			((_jedec_id) >> 16) & 0xff,			\
-			((_jedec_id) >> 8) & 0xff,			\
-			(_jedec_id) & 0xff,				\
-			((_ext_id) >> 16) & 0xff,			\
-			((_ext_id) >> 8) & 0xff,			\
-			(_ext_id) & 0xff,				\
-			},						\
-		.id_len = 6,						\
-		.sector_size = (_sector_size),				\
-		.n_sectors = (_n_sectors),				\
-		.page_size = 256,					\
-		.flags = (_flags),
-
-#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags)	\
-		.sector_size = (_sector_size),				\
-		.n_sectors = (_n_sectors),				\
-		.page_size = (_page_size),				\
-		.addr_width = (_addr_width),				\
-		.flags = (_flags),
-
-#define S3AN_INFO(_jedec_id, _n_sectors, _page_size)			\
-		.id = {							\
-			((_jedec_id) >> 16) & 0xff,			\
-			((_jedec_id) >> 8) & 0xff,			\
-			(_jedec_id) & 0xff				\
-			},						\
-		.id_len = 3,						\
-		.sector_size = (8*_page_size),				\
-		.n_sectors = (_n_sectors),				\
-		.page_size = _page_size,				\
-		.addr_width = 3,					\
-		.flags = SPI_NOR_NO_FR | SPI_S3AN,
-
 static int
 is25lp256_post_bfpt_fixups(struct spi_nor *nor,
 			   const struct sfdp_parameter_header *bfpt_header,
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index e1256fe50d12..7e2d88edf1f1 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -9,12 +9,166 @@
 
 #include "sfdp.h"
 
+#define SPI_NOR_MAX_ID_LEN	6
+
+/**
+ * struct spi_nor_fixups - SPI NOR fixup hooks
+ * @default_init: called after default flash parameters init. Used to tweak
+ *                flash parameters when information provided by the flash_info
+ *                table is incomplete or wrong.
+ * @post_bfpt: called after the BFPT table has been parsed
+ * @post_sfdp: called after SFDP has been parsed (is also called for SPI NORs
+ *             that do not support RDSFDP). Typically used to tweak various
+ *             parameters that could not be extracted by other means (i.e.
+ *             when information provided by the SFDP/flash_info tables are
+ *             incomplete or wrong).
+ *
+ * Those hooks can be used to tweak the SPI NOR configuration when the SFDP
+ * table is broken or not available.
+ */
+struct spi_nor_fixups {
+	void (*default_init)(struct spi_nor *nor);
+	int (*post_bfpt)(struct spi_nor *nor,
+			 const struct sfdp_parameter_header *bfpt_header,
+			 const struct sfdp_bfpt *bfpt,
+			 struct spi_nor_flash_parameter *params);
+	void (*post_sfdp)(struct spi_nor *nor);
+};
+
+struct flash_info {
+	char		*name;
+
+	/*
+	 * This array stores the ID bytes.
+	 * The first three bytes are the JEDIC ID.
+	 * JEDEC ID zero means "no ID" (mostly older chips).
+	 */
+	u8		id[SPI_NOR_MAX_ID_LEN];
+	u8		id_len;
+
+	/* The size listed here is what works with SPINOR_OP_SE, which isn't
+	 * necessarily called a "sector" by the vendor.
+	 */
+	unsigned	sector_size;
+	u16		n_sectors;
+
+	u16		page_size;
+	u16		addr_width;
+
+	u32		flags;
+#define SECT_4K			BIT(0)	/* SPINOR_OP_BE_4K works uniformly */
+#define SPI_NOR_NO_ERASE	BIT(1)	/* No erase command needed */
+#define SST_WRITE		BIT(2)	/* use SST byte programming */
+#define SPI_NOR_NO_FR		BIT(3)	/* Can't do fastread */
+#define SECT_4K_PMC		BIT(4)	/* SPINOR_OP_BE_4K_PMC works uniformly */
+#define SPI_NOR_DUAL_READ	BIT(5)	/* Flash supports Dual Read */
+#define SPI_NOR_QUAD_READ	BIT(6)	/* Flash supports Quad Read */
+#define USE_FSR			BIT(7)	/* use flag status register */
+#define SPI_NOR_HAS_LOCK	BIT(8)	/* Flash supports lock/unlock via SR */
+#define SPI_NOR_HAS_TB		BIT(9)	/*
+					 * Flash SR has Top/Bottom (TB) protect
+					 * bit. Must be used with
+					 * SPI_NOR_HAS_LOCK.
+					 */
+#define SPI_NOR_XSR_RDY		BIT(10)	/*
+					 * S3AN flashes have specific opcode to
+					 * read the status register.
+					 * Flags SPI_NOR_XSR_RDY and SPI_S3AN
+					 * use the same bit as one implies the
+					 * other, but we will get rid of
+					 * SPI_S3AN soon.
+					 */
+#define	SPI_S3AN		BIT(10)	/*
+					 * Xilinx Spartan 3AN In-System Flash
+					 * (MFR cannot be used for probing
+					 * because it has the same value as
+					 * ATMEL flashes)
+					 */
+#define SPI_NOR_4B_OPCODES	BIT(11)	/*
+					 * Use dedicated 4byte address op codes
+					 * to support memory size above 128Mib.
+					 */
+#define NO_CHIP_ERASE		BIT(12) /* Chip does not support chip erase */
+#define SPI_NOR_SKIP_SFDP	BIT(13)	/* Skip parsing of SFDP tables */
+#define USE_CLSR		BIT(14)	/* use CLSR command */
+#define SPI_NOR_OCTAL_READ	BIT(15)	/* Flash supports Octal Read */
+#define SPI_NOR_TB_SR_BIT6	BIT(16)	/*
+					 * Top/Bottom (TB) is bit 6 of
+					 * status register. Must be used with
+					 * SPI_NOR_HAS_TB.
+					 */
+
+	/* Part specific fixup hooks. */
+	const struct spi_nor_fixups *fixups;
+};
+
+/* Used when the "_ext_id" is two bytes at most */
+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
+		.id = {							\
+			((_jedec_id) >> 16) & 0xff,			\
+			((_jedec_id) >> 8) & 0xff,			\
+			(_jedec_id) & 0xff,				\
+			((_ext_id) >> 8) & 0xff,			\
+			(_ext_id) & 0xff,				\
+			},						\
+		.id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),	\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = 256,					\
+		.flags = (_flags),
+
+#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)	\
+		.id = {							\
+			((_jedec_id) >> 16) & 0xff,			\
+			((_jedec_id) >> 8) & 0xff,			\
+			(_jedec_id) & 0xff,				\
+			((_ext_id) >> 16) & 0xff,			\
+			((_ext_id) >> 8) & 0xff,			\
+			(_ext_id) & 0xff,				\
+			},						\
+		.id_len = 6,						\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = 256,					\
+		.flags = (_flags),
+
+#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags)	\
+		.sector_size = (_sector_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = (_page_size),				\
+		.addr_width = (_addr_width),				\
+		.flags = (_flags),
+
+#define S3AN_INFO(_jedec_id, _n_sectors, _page_size)			\
+		.id = {							\
+			((_jedec_id) >> 16) & 0xff,			\
+			((_jedec_id) >> 8) & 0xff,			\
+			(_jedec_id) & 0xff				\
+			},						\
+		.id_len = 3,						\
+		.sector_size = (8*_page_size),				\
+		.n_sectors = (_n_sectors),				\
+		.page_size = _page_size,				\
+		.addr_width = 3,					\
+		.flags = SPI_NOR_NO_FR | SPI_S3AN,
+
+int spi_nor_write_enable(struct spi_nor *nor);
+int spi_nor_write_disable(struct spi_nor *nor);
+int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable);
+int spi_nor_en4_ex4_wen_set_4byte(struct spi_nor *nor, bool enable);
+int spi_nor_write_ear(struct spi_nor *nor, u8 ear);
+int spi_nor_wait_till_ready(struct spi_nor *nor);
+int spi_nor_lock_and_prep(struct spi_nor *nor);
+void spi_nor_unlock_and_unprep(struct spi_nor *nor);
 int spi_nor_sr1_bit6_quad_enable(struct spi_nor *nor);
 int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor);
 int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor);
 
+int spi_nor_xread_sr(struct spi_nor *nor, u8 *sr);
 ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
 			  u8 *buf);
+ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
+			   const u8 *buf);
 
 int spi_nor_hwcaps_read2cmd(u32 hwcaps);
 u8 spi_nor_convert_3to4_read(u8 opcode);
@@ -33,4 +187,9 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
 			     const struct sfdp_bfpt *bfpt,
 			     struct spi_nor_flash_parameter *params);
 
+static struct spi_nor __maybe_unused *mtd_to_spi_nor(struct mtd_info *mtd)
+{
+	return mtd->priv;
+}
+
 #endif /* __LINUX_MTD_SPI_NOR_INTERNAL_H */
-- 
2.23.0

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

* [PATCH 05/23] mtd: spi-nor: Add the concept of SPI NOR manufacturer driver
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (3 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 04/23] mtd: spi-nor: Expose stuctures and functions to manufacturer drivers Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 07/23] mtd: spi-nor: Move Eon bits out of core.c Tudor.Ambarus
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Declare a spi_nor_manufacturer struct and add basic building blocks to
move manufacturer specific code outside of the core.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/core.c  | 78 +++++++++++++++++++++++++++++++------
 drivers/mtd/spi-nor/core.h  | 14 +++++++
 include/linux/mtd/spi-nor.h |  8 ++++
 3 files changed, 89 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 16cf9d4b1a73..d41ef1795707 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2472,8 +2472,26 @@ static const struct flash_info spi_nor_ids[] = {
 	{ },
 };
 
+static const struct spi_nor_manufacturer *manufacturers[0];
+
+static const struct flash_info *
+spi_nor_search_part_by_id(const struct flash_info *parts, unsigned int nparts,
+			  const u8 *id)
+{
+	unsigned int i;
+
+	for (i = 0; i < nparts; i++) {
+		if (parts[i].id_len &&
+		    !memcmp(parts[i].id, id, parts[i].id_len))
+			return &parts[i];
+	}
+
+	return NULL;
+}
+
 static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
 {
+	const struct flash_info *info;
 	u8 *id = nor->bouncebuf;
 	unsigned int i;
 	int ret;
@@ -2495,11 +2513,21 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
 		return ERR_PTR(ret);
 	}
 
-	for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) {
-		if (spi_nor_ids[i].id_len &&
-		    !memcmp(spi_nor_ids[i].id, id, spi_nor_ids[i].id_len))
-			return &spi_nor_ids[i];
+	for (i = 0; i < ARRAY_SIZE(manufacturers); i++) {
+		info = spi_nor_search_part_by_id(manufacturers[i]->parts,
+						 manufacturers[i]->nparts,
+						 id);
+		if (info) {
+			nor->manufacturer = manufacturers[i];
+			return info;
+		}
 	}
+
+	info = spi_nor_search_part_by_id(spi_nor_ids,
+					 ARRAY_SIZE(spi_nor_ids) - 1, id);
+	if (info)
+		return info;
+
 	dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
 		SPI_NOR_MAX_ID_LEN, id);
 	return ERR_PTR(-ENODEV);
@@ -2985,6 +3013,16 @@ int spi_nor_post_bfpt_fixups(struct spi_nor *nor,
 			     const struct sfdp_bfpt *bfpt,
 			     struct spi_nor_flash_parameter *params)
 {
+	int ret;
+
+	if (nor->manufacturer && nor->manufacturer->fixups &&
+	    nor->manufacturer->fixups->post_bfpt) {
+		ret = nor->manufacturer->fixups->post_bfpt(nor, bfpt_header,
+							   bfpt, params);
+		if (ret)
+			return ret;
+	}
+
 	if (nor->info->fixups && nor->info->fixups->post_bfpt)
 		return nor->info->fixups->post_bfpt(nor, bfpt_header, bfpt,
 						    params);
@@ -3294,6 +3332,10 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 		break;
 	}
 
+	if (nor->manufacturer && nor->manufacturer->fixups &&
+	    nor->manufacturer->fixups->default_init)
+		nor->manufacturer->fixups->default_init(nor);
+
 	if (nor->info->fixups && nor->info->fixups->default_init)
 		nor->info->fixups->default_init(nor);
 }
@@ -3453,6 +3495,10 @@ static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
 	if (nor->info->flags & SPI_S3AN)
 		s3an_post_sfdp_fixups(nor);
 
+	if (nor->manufacturer && nor->manufacturer->fixups &&
+	    nor->manufacturer->fixups->post_sfdp)
+		nor->manufacturer->fixups->post_sfdp(nor);
+
 	if (nor->info->fixups && nor->info->fixups->post_sfdp)
 		nor->info->fixups->post_sfdp(nor);
 }
@@ -3615,15 +3661,25 @@ void spi_nor_restore(struct spi_nor *nor)
 }
 EXPORT_SYMBOL_GPL(spi_nor_restore);
 
-static const struct flash_info *spi_nor_match_id(const char *name)
+static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
+						 const char *name)
 {
-	const struct flash_info *id = spi_nor_ids;
+	unsigned int i, j;
 
-	while (id->name) {
-		if (!strcmp(name, id->name))
-			return id;
-		id++;
+	for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) {
+		if (!strcmp(name, spi_nor_ids[i].name))
+			return &spi_nor_ids[i];
 	}
+
+	for (i = 0; i < ARRAY_SIZE(manufacturers); i++) {
+		for (j = 0; j < manufacturers[i]->nparts; j++) {
+			if (!strcmp(name, manufacturers[i]->parts[j].name)) {
+				nor->manufacturer = manufacturers[i];
+				return &manufacturers[i]->parts[j];
+			}
+		}
+	}
+
 	return NULL;
 }
 
@@ -3670,7 +3726,7 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
 	const struct flash_info *info = NULL;
 
 	if (name)
-		info = spi_nor_match_id(name);
+		info = spi_nor_match_id(nor, name);
 	/* Try to auto-detect if chip name wasn't specified or not found */
 	if (!info)
 		info = spi_nor_read_id(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 7e2d88edf1f1..89b8dd1c8213 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -152,6 +152,20 @@ struct flash_info {
 		.addr_width = 3,					\
 		.flags = SPI_NOR_NO_FR | SPI_S3AN,
 
+/**
+ * struct spi_nor_manufacturer - SPI NOR manufacturer object
+ * @name: manufacturer name
+ * @parts: array of parts supported by this manufacturer
+ * @nparts: number of entries in the parts array
+ * @fixups: hooks called at various points in time during spi_nor_scan()
+ */
+struct spi_nor_manufacturer {
+	const char *name;
+	const struct flash_info *parts;
+	unsigned int nparts;
+	const struct spi_nor_fixups *fixups;
+};
+
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
 int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable);
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index de90724f62f1..dde2988a809e 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -554,6 +554,12 @@ struct spi_nor_flash_parameter {
  */
 struct flash_info;
 
+/**
+ * struct spi_nor_manufacturer - Forward declaration of a structure used
+ * internally by the core and manufacturer drivers.
+ */
+struct spi_nor_manufacturer;
+
 /**
  * struct spi_nor - Structure for defining a the SPI NOR layer
  * @mtd:		point to a mtd_info structure
@@ -564,6 +570,7 @@ struct flash_info;
  *                      layer is not DMA-able
  * @bouncebuf_size:	size of the bounce buffer
  * @info:		spi-nor part JDEC MFR id and other info
+ * @manufacturer:	spi-nor manufacturer
  * @page_size:		the page size of the SPI NOR
  * @addr_width:		number of address bytes
  * @erase_opcode:	the opcode for erasing a sector
@@ -591,6 +598,7 @@ struct spi_nor {
 	u8			*bouncebuf;
 	size_t			bouncebuf_size;
 	const struct flash_info	*info;
+	const struct spi_nor_manufacturer *manufacturer;
 	u32			page_size;
 	u8			addr_width;
 	u8			erase_opcode;
-- 
2.23.0

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

* [PATCH 06/23] mtd: spi-nor: Move Atmel bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (5 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 07/23] mtd: spi-nor: Move Eon bits out of core.c Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 08/23] mtd: spi-nor: Move ESMT " Tudor.Ambarus
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Atmel chips, and move the
Atmel definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |  1 +
 drivers/mtd/spi-nor/atmel.c  | 46 ++++++++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.c   | 32 +++----------------------
 drivers/mtd/spi-nor/core.h   |  3 +++
 4 files changed, 53 insertions(+), 29 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/atmel.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 6bcdb6f1615a..0a243592e416 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
 spi-nor-objs			:= core.o sfdp.o
+spi-nor-objs			+= atmel.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/atmel.c b/drivers/mtd/spi-nor/atmel.c
new file mode 100644
index 000000000000..3f5f21a473a6
--- /dev/null
+++ b/drivers/mtd/spi-nor/atmel.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info atmel_parts[] = {
+	/* Atmel -- some are (confusingly) marketed as "DataFlash" */
+	{ "at25fs010",  INFO(0x1f6601, 0, 32 * 1024,   4, SECT_4K) },
+	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
+
+	{ "at25df041a", INFO(0x1f4401, 0, 64 * 1024,   8, SECT_4K) },
+	{ "at25df321",  INFO(0x1f4700, 0, 64 * 1024,  64, SECT_4K) },
+	{ "at25df321a", INFO(0x1f4701, 0, 64 * 1024,  64, SECT_4K) },
+	{ "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
+
+	{ "at25sl321",	INFO(0x1f4216, 0, 64 * 1024, 64,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+
+	{ "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, SECT_4K) },
+	{ "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
+	{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
+	{ "at26df321",  INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
+
+	{ "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
+};
+
+static void atmel_default_init(struct spi_nor *nor)
+{
+	nor->flags |= SNOR_F_HAS_LOCK;
+}
+
+static const struct spi_nor_fixups atmel_fixups = {
+	.default_init = atmel_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_atmel = {
+	.name = "atmel",
+	.parts = atmel_parts,
+	.nparts = ARRAY_SIZE(atmel_parts),
+	.fixups = &atmel_fixups,
+};
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index d41ef1795707..45d370229e0a 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2079,25 +2079,6 @@ static struct spi_nor_fixups gd25q256_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Atmel -- some are (confusingly) marketed as "DataFlash" */
-	{ "at25fs010",  INFO(0x1f6601, 0, 32 * 1024,   4, SECT_4K) },
-	{ "at25fs040",  INFO(0x1f6604, 0, 64 * 1024,   8, SECT_4K) },
-
-	{ "at25df041a", INFO(0x1f4401, 0, 64 * 1024,   8, SECT_4K) },
-	{ "at25df321",  INFO(0x1f4700, 0, 64 * 1024,  64, SECT_4K) },
-	{ "at25df321a", INFO(0x1f4701, 0, 64 * 1024,  64, SECT_4K) },
-	{ "at25df641",  INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
-
-	{ "at25sl321",	INFO(0x1f4216, 0, 64 * 1024, 64,
-			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-
-	{ "at26f004",   INFO(0x1f0400, 0, 64 * 1024,  8, SECT_4K) },
-	{ "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
-	{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
-	{ "at26df321",  INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
-
-	{ "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
-
 	/* EON -- en25xxx */
 	{ "en25f32",    INFO(0x1c3116, 0, 64 * 1024,   64, SECT_4K) },
 	{ "en25p32",    INFO(0x1c2016, 0, 64 * 1024,   64, 0) },
@@ -2472,7 +2453,9 @@ static const struct flash_info spi_nor_ids[] = {
 	{ },
 };
 
-static const struct spi_nor_manufacturer *manufacturers[0];
+static const struct spi_nor_manufacturer *manufacturers[] = {
+	&spi_nor_atmel,
+};
 
 static const struct flash_info *
 spi_nor_search_part_by_id(const struct flash_info *parts, unsigned int nparts,
@@ -3251,11 +3234,6 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return nor->params.setup(nor, hwcaps);
 }
 
-static void atmel_set_default_init(struct spi_nor *nor)
-{
-	nor->flags |= SNOR_F_HAS_LOCK;
-}
-
 static void intel_set_default_init(struct spi_nor *nor)
 {
 	nor->flags |= SNOR_F_HAS_LOCK;
@@ -3299,10 +3277,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 {
 	/* Init flash parameters based on MFR */
 	switch (JEDEC_MFR(nor->info)) {
-	case SNOR_MFR_ATMEL:
-		atmel_set_default_init(nor);
-		break;
-
 	case SNOR_MFR_INTEL:
 		intel_set_default_init(nor);
 		break;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 89b8dd1c8213..505e580add68 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -166,6 +166,9 @@ struct spi_nor_manufacturer {
 	const struct spi_nor_fixups *fixups;
 };
 
+/* Manufacturer drivers. */
+extern const struct spi_nor_manufacturer spi_nor_atmel;
+
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
 int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable);
-- 
2.23.0

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

* [PATCH 07/23] mtd: spi-nor: Move Eon bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (4 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 05/23] mtd: spi-nor: Add the concept of SPI NOR manufacturer driver Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 06/23] mtd: spi-nor: Move Atmel " Tudor.Ambarus
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Eon chips, and move the
Eon definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |  1 +
 drivers/mtd/spi-nor/core.c   | 18 +-----------------
 drivers/mtd/spi-nor/core.h   |  1 +
 drivers/mtd/spi-nor/eon.c    | 34 ++++++++++++++++++++++++++++++++++
 4 files changed, 37 insertions(+), 17 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/eon.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 0a243592e416..e1bc8ccfe14d 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -2,4 +2,5 @@
 
 spi-nor-objs			:= core.o sfdp.o
 spi-nor-objs			+= atmel.o
+spi-nor-objs			+= eon.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 45d370229e0a..67a3493939f6 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2079,23 +2079,6 @@ static struct spi_nor_fixups gd25q256_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* EON -- en25xxx */
-	{ "en25f32",    INFO(0x1c3116, 0, 64 * 1024,   64, SECT_4K) },
-	{ "en25p32",    INFO(0x1c2016, 0, 64 * 1024,   64, 0) },
-	{ "en25q32b",   INFO(0x1c3016, 0, 64 * 1024,   64, 0) },
-	{ "en25p64",    INFO(0x1c2017, 0, 64 * 1024,  128, 0) },
-	{ "en25q64",    INFO(0x1c3017, 0, 64 * 1024,  128, SECT_4K) },
-	{ "en25q80a",   INFO(0x1c3014, 0, 64 * 1024,   16,
-			SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "en25qh16",   INFO(0x1c7015, 0, 64 * 1024,   32,
-			SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "en25qh32",   INFO(0x1c7016, 0, 64 * 1024,   64, 0) },
-	{ "en25qh64",   INFO(0x1c7017, 0, 64 * 1024,  128,
-			SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "en25qh128",  INFO(0x1c7018, 0, 64 * 1024,  256, 0) },
-	{ "en25qh256",  INFO(0x1c7019, 0, 64 * 1024,  512, 0) },
-	{ "en25s64",	INFO(0x1c3817, 0, 64 * 1024,  128, SECT_4K) },
-
 	/* ESMT */
 	{ "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
 	{ "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
@@ -2455,6 +2438,7 @@ static const struct flash_info spi_nor_ids[] = {
 
 static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_atmel,
+	&spi_nor_eon,
 };
 
 static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 505e580add68..1ac226c456e1 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -168,6 +168,7 @@ struct spi_nor_manufacturer {
 
 /* Manufacturer drivers. */
 extern const struct spi_nor_manufacturer spi_nor_atmel;
+extern const struct spi_nor_manufacturer spi_nor_eon;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/eon.c b/drivers/mtd/spi-nor/eon.c
new file mode 100644
index 000000000000..ddb8e3650835
--- /dev/null
+++ b/drivers/mtd/spi-nor/eon.c
@@ -0,0 +1,34 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info eon_parts[] = {
+	/* EON -- en25xxx */
+	{ "en25f32",    INFO(0x1c3116, 0, 64 * 1024,   64, SECT_4K) },
+	{ "en25p32",    INFO(0x1c2016, 0, 64 * 1024,   64, 0) },
+	{ "en25q32b",   INFO(0x1c3016, 0, 64 * 1024,   64, 0) },
+	{ "en25p64",    INFO(0x1c2017, 0, 64 * 1024,  128, 0) },
+	{ "en25q64",    INFO(0x1c3017, 0, 64 * 1024,  128, SECT_4K) },
+	{ "en25q80a",   INFO(0x1c3014, 0, 64 * 1024,   16,
+			     SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "en25qh16",   INFO(0x1c7015, 0, 64 * 1024,   32,
+			     SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "en25qh32",   INFO(0x1c7016, 0, 64 * 1024,   64, 0) },
+	{ "en25qh64",   INFO(0x1c7017, 0, 64 * 1024,  128,
+			     SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "en25qh128",  INFO(0x1c7018, 0, 64 * 1024,  256, 0) },
+	{ "en25qh256",  INFO(0x1c7019, 0, 64 * 1024,  512, 0) },
+	{ "en25s64",	INFO(0x1c3817, 0, 64 * 1024,  128, SECT_4K) },
+};
+
+const struct spi_nor_manufacturer spi_nor_eon = {
+	.name = "eon",
+	.parts = eon_parts,
+	.nparts = ARRAY_SIZE(eon_parts),
+};
-- 
2.23.0

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

* [PATCH 08/23] mtd: spi-nor: Move ESMT bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (6 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 06/23] mtd: spi-nor: Move Atmel " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 09/23] mtd: spi-nor: Move Everspin " Tudor.Ambarus
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for ESMT chips, and move the
ESMT definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |  1 +
 drivers/mtd/spi-nor/core.c   |  6 +-----
 drivers/mtd/spi-nor/core.h   |  1 +
 drivers/mtd/spi-nor/esmt.c   | 25 +++++++++++++++++++++++++
 4 files changed, 28 insertions(+), 5 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/esmt.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index e1bc8ccfe14d..4e5ef10e4fd7 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -3,4 +3,5 @@
 spi-nor-objs			:= core.o sfdp.o
 spi-nor-objs			+= atmel.o
 spi-nor-objs			+= eon.o
+spi-nor-objs			+= esmt.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 67a3493939f6..30a0ddc6de81 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2079,11 +2079,6 @@ static struct spi_nor_fixups gd25q256_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* ESMT */
-	{ "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
-	{ "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
-	{ "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_LOCK) },
-
 	/* Everspin */
 	{ "mr25h128", CAT25_INFO( 16 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
 	{ "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
@@ -2439,6 +2434,7 @@ static const struct flash_info spi_nor_ids[] = {
 static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_atmel,
 	&spi_nor_eon,
+	&spi_nor_esmt,
 };
 
 static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 1ac226c456e1..23ce99fb8087 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -169,6 +169,7 @@ struct spi_nor_manufacturer {
 /* Manufacturer drivers. */
 extern const struct spi_nor_manufacturer spi_nor_atmel;
 extern const struct spi_nor_manufacturer spi_nor_eon;
+extern const struct spi_nor_manufacturer spi_nor_esmt;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/esmt.c b/drivers/mtd/spi-nor/esmt.c
new file mode 100644
index 000000000000..c93170008118
--- /dev/null
+++ b/drivers/mtd/spi-nor/esmt.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info esmt_parts[] = {
+	/* ESMT */
+	{ "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64,
+			   SECT_4K | SPI_NOR_HAS_LOCK) },
+	{ "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64,
+			   SECT_4K | SPI_NOR_HAS_LOCK) },
+	{ "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128,
+			   SECT_4K | SPI_NOR_HAS_LOCK) },
+};
+
+const struct spi_nor_manufacturer spi_nor_esmt = {
+	.name = "esmt",
+	.parts = esmt_parts,
+	.nparts = ARRAY_SIZE(esmt_parts),
+};
-- 
2.23.0

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

* [PATCH 09/23] mtd: spi-nor: Move Everspin bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (7 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 08/23] mtd: spi-nor: Move ESMT " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 10/23] mtd: spi-nor: Move Fujitsu " Tudor.Ambarus
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Everspin chips, and move the
Everspin definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile   |  1 +
 drivers/mtd/spi-nor/core.c     |  7 +------
 drivers/mtd/spi-nor/core.h     |  1 +
 drivers/mtd/spi-nor/everspin.c | 27 +++++++++++++++++++++++++++
 4 files changed, 30 insertions(+), 6 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/everspin.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 4e5ef10e4fd7..384c520689d8 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -4,4 +4,5 @@ spi-nor-objs			:= core.o sfdp.o
 spi-nor-objs			+= atmel.o
 spi-nor-objs			+= eon.o
 spi-nor-objs			+= esmt.o
+spi-nor-objs			+= everspin.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 30a0ddc6de81..07eec3476053 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2079,12 +2079,6 @@ static struct spi_nor_fixups gd25q256_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Everspin */
-	{ "mr25h128", CAT25_INFO( 16 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-	{ "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-	{ "mr25h10",  CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-	{ "mr25h40",  CAT25_INFO(512 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-
 	/* Fujitsu */
 	{ "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) },
 
@@ -2435,6 +2429,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_atmel,
 	&spi_nor_eon,
 	&spi_nor_esmt,
+	&spi_nor_everspin,
 };
 
 static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 23ce99fb8087..d36e7f93dbcf 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -170,6 +170,7 @@ struct spi_nor_manufacturer {
 extern const struct spi_nor_manufacturer spi_nor_atmel;
 extern const struct spi_nor_manufacturer spi_nor_eon;
 extern const struct spi_nor_manufacturer spi_nor_esmt;
+extern const struct spi_nor_manufacturer spi_nor_everspin;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/everspin.c b/drivers/mtd/spi-nor/everspin.c
new file mode 100644
index 000000000000..04a177a32283
--- /dev/null
+++ b/drivers/mtd/spi-nor/everspin.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info everspin_parts[] = {
+	/* Everspin */
+	{ "mr25h128", CAT25_INFO(16 * 1024, 1, 256, 2,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "mr25h256", CAT25_INFO(32 * 1024, 1, 256, 2,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "mr25h10",  CAT25_INFO(128 * 1024, 1, 256, 3,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "mr25h40",  CAT25_INFO(512 * 1024, 1, 256, 3,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+};
+
+const struct spi_nor_manufacturer spi_nor_everspin = {
+	.name = "everspin",
+	.parts = everspin_parts,
+	.nparts = ARRAY_SIZE(everspin_parts),
+};
-- 
2.23.0

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

* [PATCH 10/23] mtd: spi-nor: Move Fujitsu bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (8 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 09/23] mtd: spi-nor: Move Everspin " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 12/23] mtd: spi-nor: Move Intel " Tudor.Ambarus
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Fujitsu chips, and move the
Fujitsu definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile  |  1 +
 drivers/mtd/spi-nor/core.c    |  4 +---
 drivers/mtd/spi-nor/core.h    |  1 +
 drivers/mtd/spi-nor/fujitsu.c | 20 ++++++++++++++++++++
 4 files changed, 23 insertions(+), 3 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/fujitsu.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 384c520689d8..ca6222d98b0f 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -5,4 +5,5 @@ spi-nor-objs			+= atmel.o
 spi-nor-objs			+= eon.o
 spi-nor-objs			+= esmt.o
 spi-nor-objs			+= everspin.o
+spi-nor-objs			+= fujitsu.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 07eec3476053..3f3955bbbb70 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2079,9 +2079,6 @@ static struct spi_nor_fixups gd25q256_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Fujitsu */
-	{ "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) },
-
 	/* GigaDevice */
 	{
 		"gd25q16", INFO(0xc84015, 0, 64 * 1024,  32,
@@ -2430,6 +2427,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_eon,
 	&spi_nor_esmt,
 	&spi_nor_everspin,
+	&spi_nor_fujitsu,
 };
 
 static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index d36e7f93dbcf..1b9f7402e5ff 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -171,6 +171,7 @@ extern const struct spi_nor_manufacturer spi_nor_atmel;
 extern const struct spi_nor_manufacturer spi_nor_eon;
 extern const struct spi_nor_manufacturer spi_nor_esmt;
 extern const struct spi_nor_manufacturer spi_nor_everspin;
+extern const struct spi_nor_manufacturer spi_nor_fujitsu;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/fujitsu.c b/drivers/mtd/spi-nor/fujitsu.c
new file mode 100644
index 000000000000..e385d93e756c
--- /dev/null
+++ b/drivers/mtd/spi-nor/fujitsu.c
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info fujitsu_parts[] = {
+	/* Fujitsu */
+	{ "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) },
+};
+
+const struct spi_nor_manufacturer spi_nor_fujitsu = {
+	.name = "fujitsu",
+	.parts = fujitsu_parts,
+	.nparts = ARRAY_SIZE(fujitsu_parts),
+};
-- 
2.23.0

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

* [PATCH 11/23] mtd: spi-nor: Move GigaDevice bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (10 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 12/23] mtd: spi-nor: Move Intel " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 13/23] mtd: spi-nor: Move ISSI " Tudor.Ambarus
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for GigaDevice chips, and move the
GigaDevice definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile     |  1 +
 drivers/mtd/spi-nor/core.c       | 60 +-------------------------------
 drivers/mtd/spi-nor/core.h       |  1 +
 drivers/mtd/spi-nor/gigadevice.c | 59 +++++++++++++++++++++++++++++++
 4 files changed, 62 insertions(+), 59 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/gigadevice.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index ca6222d98b0f..38f704be4b03 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -6,4 +6,5 @@ spi-nor-objs			+= eon.o
 spi-nor-objs			+= esmt.o
 spi-nor-objs			+= everspin.o
 spi-nor-objs			+= fujitsu.o
+spi-nor-objs			+= gigadevice.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 3f3955bbbb70..8520423b1104 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2052,21 +2052,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
 	.post_bfpt = mx25l25635_post_bfpt_fixups,
 };
 
-static void gd25q256_default_init(struct spi_nor *nor)
-{
-	/*
-	 * Some manufacturer like GigaDevice may use different
-	 * bit to set QE on different memories, so the MFR can't
-	 * indicate the quad_enable method for this case, we need
-	 * to set it in the default_init fixup hook.
-	 */
-	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
-}
-
-static struct spi_nor_fixups gd25q256_fixups = {
-	.default_init = gd25q256_default_init,
-};
-
 /* NOTE: double check command sets and memory organization when you add
  * more nor chips.  This current list focusses on newer chips, which
  * have been converging on command sets which including JEDEC ID.
@@ -2079,50 +2064,6 @@ static struct spi_nor_fixups gd25q256_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* GigaDevice */
-	{
-		"gd25q16", INFO(0xc84015, 0, 64 * 1024,  32,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"gd25q32", INFO(0xc84016, 0, 64 * 1024,  64,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"gd25lq32", INFO(0xc86016, 0, 64 * 1024, 64,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"gd25q64", INFO(0xc84017, 0, 64 * 1024, 128,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"gd25lq128d", INFO(0xc86018, 0, 64 * 1024, 256,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"gd25q128", INFO(0xc84018, 0, 64 * 1024, 256,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB |
-			SPI_NOR_TB_SR_BIT6)
-			.fixups = &gd25q256_fixups,
-	},
-
 	/* Intel/Numonyx -- xxxs33b */
 	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
 	{ "320s33b",  INFO(0x898912, 0, 64 * 1024,  64, 0) },
@@ -2428,6 +2369,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_esmt,
 	&spi_nor_everspin,
 	&spi_nor_fujitsu,
+	&spi_nor_gigadevice,
 };
 
 static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 1b9f7402e5ff..c44802a05532 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -172,6 +172,7 @@ extern const struct spi_nor_manufacturer spi_nor_eon;
 extern const struct spi_nor_manufacturer spi_nor_esmt;
 extern const struct spi_nor_manufacturer spi_nor_everspin;
 extern const struct spi_nor_manufacturer spi_nor_fujitsu;
+extern const struct spi_nor_manufacturer spi_nor_gigadevice;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
new file mode 100644
index 000000000000..7930e4490dab
--- /dev/null
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static void gd25q256_default_init(struct spi_nor *nor)
+{
+	/*
+	 * Some manufacturer like GigaDevice may use different
+	 * bit to set QE on different memories, so the MFR can't
+	 * indicate the quad_enable method for this case, we need
+	 * to set it in the default_init fixup hook.
+	 */
+	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+}
+
+static struct spi_nor_fixups gd25q256_fixups = {
+	.default_init = gd25q256_default_init,
+};
+
+static const struct flash_info gigadevice_parts[] = {
+	{ "gd25q16", INFO(0xc84015, 0, 64 * 1024,  32,
+			  SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			  SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "gd25q32", INFO(0xc84016, 0, 64 * 1024,  64,
+			  SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			  SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "gd25lq32", INFO(0xc86016, 0, 64 * 1024, 64,
+			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128,
+			  SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			  SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "gd25lq64c", INFO(0xc86017, 0, 64 * 1024, 128,
+			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			    SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "gd25lq128d", INFO(0xc86018, 0, 64 * 1024, 256,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256,
+			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "gd25q256", INFO(0xc84019, 0, 64 * 1024, 512,
+			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			   SPI_NOR_4B_OPCODES | SPI_NOR_HAS_LOCK |
+			   SPI_NOR_HAS_TB | SPI_NOR_TB_SR_BIT6)
+		.fixups = &gd25q256_fixups },
+};
+
+const struct spi_nor_manufacturer spi_nor_gigadevice = {
+	.name = "gigadevice",
+	.parts = gigadevice_parts,
+	.nparts = ARRAY_SIZE(gigadevice_parts),
+};
-- 
2.23.0

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

* [PATCH 12/23] mtd: spi-nor: Move Intel bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (9 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 10/23] mtd: spi-nor: Move Fujitsu " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-03 10:22   ` Mika Westerberg
  2020-03-02 18:07 ` [PATCH 11/23] mtd: spi-nor: Move GigaDevice " Tudor.Ambarus
                   ` (12 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Intel chips, and move the
Intel definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |  1 +
 drivers/mtd/spi-nor/core.c   | 15 +--------------
 drivers/mtd/spi-nor/core.h   |  1 +
 drivers/mtd/spi-nor/intel.c  | 32 ++++++++++++++++++++++++++++++++
 4 files changed, 35 insertions(+), 14 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/intel.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 38f704be4b03..8eb741a27fa7 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -7,4 +7,5 @@ spi-nor-objs			+= esmt.o
 spi-nor-objs			+= everspin.o
 spi-nor-objs			+= fujitsu.o
 spi-nor-objs			+= gigadevice.o
+spi-nor-objs			+= intel.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 8520423b1104..2f47852a3a01 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2064,11 +2064,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Intel/Numonyx -- xxxs33b */
-	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
-	{ "320s33b",  INFO(0x898912, 0, 64 * 1024,  64, 0) },
-	{ "640s33b",  INFO(0x898913, 0, 64 * 1024, 128, 0) },
-
 	/* ISSI */
 	{ "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2, SECT_4K) },
 	{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8,
@@ -2370,6 +2365,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_everspin,
 	&spi_nor_fujitsu,
 	&spi_nor_gigadevice,
+	&spi_nor_intel,
 };
 
 static const struct flash_info *
@@ -3149,11 +3145,6 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return nor->params.setup(nor, hwcaps);
 }
 
-static void intel_set_default_init(struct spi_nor *nor)
-{
-	nor->flags |= SNOR_F_HAS_LOCK;
-}
-
 static void issi_set_default_init(struct spi_nor *nor)
 {
 	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
@@ -3192,10 +3183,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 {
 	/* Init flash parameters based on MFR */
 	switch (JEDEC_MFR(nor->info)) {
-	case SNOR_MFR_INTEL:
-		intel_set_default_init(nor);
-		break;
-
 	case SNOR_MFR_ISSI:
 		issi_set_default_init(nor);
 		break;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index c44802a05532..c4c23efaa68b 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -173,6 +173,7 @@ extern const struct spi_nor_manufacturer spi_nor_esmt;
 extern const struct spi_nor_manufacturer spi_nor_everspin;
 extern const struct spi_nor_manufacturer spi_nor_fujitsu;
 extern const struct spi_nor_manufacturer spi_nor_gigadevice;
+extern const struct spi_nor_manufacturer spi_nor_intel;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/intel.c b/drivers/mtd/spi-nor/intel.c
new file mode 100644
index 000000000000..d8196f101368
--- /dev/null
+++ b/drivers/mtd/spi-nor/intel.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info intel_parts[] = {
+	/* Intel/Numonyx -- xxxs33b */
+	{ "160s33b",  INFO(0x898911, 0, 64 * 1024,  32, 0) },
+	{ "320s33b",  INFO(0x898912, 0, 64 * 1024,  64, 0) },
+	{ "640s33b",  INFO(0x898913, 0, 64 * 1024, 128, 0) },
+};
+
+static void intel_default_init(struct spi_nor *nor)
+{
+	nor->flags |= SNOR_F_HAS_LOCK;
+}
+
+static const struct spi_nor_fixups intel_fixups = {
+	.default_init = intel_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_intel = {
+	.name = "intel",
+	.parts = intel_parts,
+	.nparts = ARRAY_SIZE(intel_parts),
+	.fixups = &intel_fixups,
+};
-- 
2.23.0

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

* [PATCH 13/23] mtd: spi-nor: Move ISSI bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (11 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 11/23] mtd: spi-nor: Move GigaDevice " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 14/23] mtd: spi-nor: Move Macronix " Tudor.Ambarus
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for ISSI chips, and move the
ISSI definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |  1 +
 drivers/mtd/spi-nor/core.c   | 66 +---------------------------
 drivers/mtd/spi-nor/core.h   |  1 +
 drivers/mtd/spi-nor/issi.c   | 83 ++++++++++++++++++++++++++++++++++++
 4 files changed, 86 insertions(+), 65 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/issi.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 8eb741a27fa7..5c849f104cc4 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -8,4 +8,5 @@ spi-nor-objs			+= everspin.o
 spi-nor-objs			+= fujitsu.o
 spi-nor-objs			+= gigadevice.o
 spi-nor-objs			+= intel.o
+spi-nor-objs			+= issi.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 2f47852a3a01..d781cb9af182 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2005,28 +2005,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
 	return 0;
 }
 
-static int
-is25lp256_post_bfpt_fixups(struct spi_nor *nor,
-			   const struct sfdp_parameter_header *bfpt_header,
-			   const struct sfdp_bfpt *bfpt,
-			   struct spi_nor_flash_parameter *params)
-{
-	/*
-	 * IS25LP256 supports 4B opcodes, but the BFPT advertises a
-	 * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY address width.
-	 * Overwrite the address width advertised by the BFPT.
-	 */
-	if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
-		BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
-		nor->addr_width = 4;
-
-	return 0;
-}
-
-static struct spi_nor_fixups is25lp256_fixups = {
-	.post_bfpt = is25lp256_post_bfpt_fixups,
-};
-
 static int
 mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
 			    const struct sfdp_parameter_header *bfpt_header,
@@ -2064,35 +2042,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* ISSI */
-	{ "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2, SECT_4K) },
-	{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "is25lp016d", INFO(0x9d6015, 0, 64 * 1024,  32,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "is25lp080d", INFO(0x9d6014, 0, 64 * 1024,  16,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "is25lp032",  INFO(0x9d6016, 0, 64 * 1024,  64,
-			SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "is25lp064",  INFO(0x9d6017, 0, 64 * 1024, 128,
-			SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256,
-			SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_4B_OPCODES)
-			.fixups = &is25lp256_fixups },
-	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
-			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			    SPI_NOR_4B_OPCODES)
-		       .fixups = &is25lp256_fixups },
-
 	/* Macronix */
 	{ "mx25l512e",   INFO(0xc22010, 0, 64 * 1024,   1, SECT_4K) },
 	{ "mx25l2005a",  INFO(0xc22012, 0, 64 * 1024,   4, SECT_4K) },
@@ -2173,11 +2122,6 @@ static const struct flash_info spi_nor_ids[] = {
 			     SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
 			     SPI_NOR_4B_OPCODES) },
 
-	/* PMC */
-	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
-	{ "pm25lv010",   INFO(0,        0, 32 * 1024,    4, SECT_4K_PMC) },
-	{ "pm25lq032",   INFO(0x7f9d46, 0, 64 * 1024,   64, SECT_4K) },
-
 	/* Spansion/Cypress -- single (large) sector size only, at least
 	 * for the chips listed here (without boot sectors).
 	 */
@@ -2366,6 +2310,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_fujitsu,
 	&spi_nor_gigadevice,
 	&spi_nor_intel,
+	&spi_nor_issi,
 };
 
 static const struct flash_info *
@@ -3145,11 +3090,6 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return nor->params.setup(nor, hwcaps);
 }
 
-static void issi_set_default_init(struct spi_nor *nor)
-{
-	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
-}
-
 static void macronix_set_default_init(struct spi_nor *nor)
 {
 	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
@@ -3183,10 +3123,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 {
 	/* Init flash parameters based on MFR */
 	switch (JEDEC_MFR(nor->info)) {
-	case SNOR_MFR_ISSI:
-		issi_set_default_init(nor);
-		break;
-
 	case SNOR_MFR_MACRONIX:
 		macronix_set_default_init(nor);
 		break;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index c4c23efaa68b..b4ed9acbef63 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -174,6 +174,7 @@ extern const struct spi_nor_manufacturer spi_nor_everspin;
 extern const struct spi_nor_manufacturer spi_nor_fujitsu;
 extern const struct spi_nor_manufacturer spi_nor_gigadevice;
 extern const struct spi_nor_manufacturer spi_nor_intel;
+extern const struct spi_nor_manufacturer spi_nor_issi;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
new file mode 100644
index 000000000000..3a1c34c41388
--- /dev/null
+++ b/drivers/mtd/spi-nor/issi.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static int
+is25lp256_post_bfpt_fixups(struct spi_nor *nor,
+			   const struct sfdp_parameter_header *bfpt_header,
+			   const struct sfdp_bfpt *bfpt,
+			   struct spi_nor_flash_parameter *params)
+{
+	/*
+	 * IS25LP256 supports 4B opcodes, but the BFPT advertises a
+	 * BFPT_DWORD1_ADDRESS_BYTES_3_ONLY address width.
+	 * Overwrite the address width advertised by the BFPT.
+	 */
+	if ((bfpt->dwords[BFPT_DWORD(1)] & BFPT_DWORD1_ADDRESS_BYTES_MASK) ==
+		BFPT_DWORD1_ADDRESS_BYTES_3_ONLY)
+		nor->addr_width = 4;
+
+	return 0;
+}
+
+static struct spi_nor_fixups is25lp256_fixups = {
+	.post_bfpt = is25lp256_post_bfpt_fixups,
+};
+
+static const struct flash_info issi_parts[] = {
+	/* ISSI */
+	{ "is25cd512",  INFO(0x7f9d20, 0, 32 * 1024,   2, SECT_4K) },
+	{ "is25lq040b", INFO(0x9d4013, 0, 64 * 1024,   8,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "is25lp016d", INFO(0x9d6015, 0, 64 * 1024,  32,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "is25lp080d", INFO(0x9d6014, 0, 64 * 1024,  16,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "is25lp032",  INFO(0x9d6016, 0, 64 * 1024,  64,
+			     SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "is25lp064",  INFO(0x9d6017, 0, 64 * 1024, 128,
+			     SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "is25lp128",  INFO(0x9d6018, 0, 64 * 1024, 256,
+			     SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "is25lp256",  INFO(0x9d6019, 0, 64 * 1024, 512,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     SPI_NOR_4B_OPCODES)
+		.fixups = &is25lp256_fixups },
+	{ "is25wp032",  INFO(0x9d7016, 0, 64 * 1024,  64,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "is25wp064",  INFO(0x9d7017, 0, 64 * 1024, 128,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "is25wp128",  INFO(0x9d7018, 0, 64 * 1024, 256,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "is25wp256", INFO(0x9d7019, 0, 64 * 1024, 512,
+			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			    SPI_NOR_4B_OPCODES)
+		.fixups = &is25lp256_fixups },
+
+	/* PMC */
+	{ "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
+	{ "pm25lv010",   INFO(0,        0, 32 * 1024,    4, SECT_4K_PMC) },
+	{ "pm25lq032",   INFO(0x7f9d46, 0, 64 * 1024,   64, SECT_4K) },
+};
+
+static void issi_default_init(struct spi_nor *nor)
+{
+	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+}
+
+static const struct spi_nor_fixups issi_fixups = {
+	.default_init = issi_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_issi = {
+	.name = "issi",
+	.parts = issi_parts,
+	.nparts = ARRAY_SIZE(issi_parts),
+	.fixups = &issi_fixups,
+};
-- 
2.23.0

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

* [PATCH 14/23] mtd: spi-nor: Move Macronix bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (12 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 13/23] mtd: spi-nor: Move ISSI " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-04  7:20   ` chenxiang (M)
  2020-03-02 18:07 ` [PATCH 16/23] mtd: spi-nor: Move Spansion " Tudor.Ambarus
                   ` (9 subsequent siblings)
  23 siblings, 1 reply; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Macronix chips, and move the
Macronix definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile   |  1 +
 drivers/mtd/spi-nor/core.c     | 69 +-----------------------
 drivers/mtd/spi-nor/core.h     |  1 +
 drivers/mtd/spi-nor/macronix.c | 98 ++++++++++++++++++++++++++++++++++
 4 files changed, 101 insertions(+), 68 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/macronix.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 5c849f104cc4..c94798987801 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -9,4 +9,5 @@ spi-nor-objs			+= fujitsu.o
 spi-nor-objs			+= gigadevice.o
 spi-nor-objs			+= intel.o
 spi-nor-objs			+= issi.o
+spi-nor-objs			+= macronix.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index d781cb9af182..9d0e0fc5af45 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2005,31 +2005,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
 	return 0;
 }
 
-static int
-mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
-			    const struct sfdp_parameter_header *bfpt_header,
-			    const struct sfdp_bfpt *bfpt,
-			    struct spi_nor_flash_parameter *params)
-{
-	/*
-	 * MX25L25635F supports 4B opcodes but MX25L25635E does not.
-	 * Unfortunately, Macronix has re-used the same JEDEC ID for both
-	 * variants which prevents us from defining a new entry in the parts
-	 * table.
-	 * We need a way to differentiate MX25L25635E and MX25L25635F, and it
-	 * seems that the F version advertises support for Fast Read 4-4-4 in
-	 * its BFPT table.
-	 */
-	if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
-		nor->flags |= SNOR_F_4B_OPCODES;
-
-	return 0;
-}
-
-static struct spi_nor_fixups mx25l25635_fixups = {
-	.post_bfpt = mx25l25635_post_bfpt_fixups,
-};
-
 /* NOTE: double check command sets and memory organization when you add
  * more nor chips.  This current list focusses on newer chips, which
  * have been converging on command sets which including JEDEC ID.
@@ -2042,39 +2017,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Macronix */
-	{ "mx25l512e",   INFO(0xc22010, 0, 64 * 1024,   1, SECT_4K) },
-	{ "mx25l2005a",  INFO(0xc22012, 0, 64 * 1024,   4, SECT_4K) },
-	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
-	{ "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, 0) },
-	{ "mx25l1606e",  INFO(0xc22015, 0, 64 * 1024,  32, SECT_4K) },
-	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, SECT_4K) },
-	{ "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
-	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
-	{ "mx25u2033e",  INFO(0xc22532, 0, 64 * 1024,   4, SECT_4K) },
-	{ "mx25u3235f",	 INFO(0xc22536, 0, 64 * 1024,  64,
-			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "mx25u4035",   INFO(0xc22533, 0, 64 * 1024,   8, SECT_4K) },
-	{ "mx25u8035",   INFO(0xc22534, 0, 64 * 1024,  16, SECT_4K) },
-	{ "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
-	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
-	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
-	{ "mx25r3235f",  INFO(0xc22816, 0, 64 * 1024,  64,
-			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
-			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
-			 SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
-			 .fixups = &mx25l25635_fixups },
-	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
-	{ "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
-			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
-	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
-
 	/* Micron <--> ST Micro */
 	{ "n25q016a",	 INFO(0x20bb15, 0, 64 * 1024,   32, SECT_4K | SPI_NOR_QUAD_READ) },
 	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
@@ -2311,6 +2253,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_gigadevice,
 	&spi_nor_intel,
 	&spi_nor_issi,
+	&spi_nor_macronix,
 };
 
 static const struct flash_info *
@@ -3090,12 +3033,6 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return nor->params.setup(nor, hwcaps);
 }
 
-static void macronix_set_default_init(struct spi_nor *nor)
-{
-	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
-	nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
-}
-
 static void sst_set_default_init(struct spi_nor *nor)
 {
 	nor->flags |= SNOR_F_HAS_LOCK;
@@ -3123,10 +3060,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 {
 	/* Init flash parameters based on MFR */
 	switch (JEDEC_MFR(nor->info)) {
-	case SNOR_MFR_MACRONIX:
-		macronix_set_default_init(nor);
-		break;
-
 	case SNOR_MFR_ST:
 	case SNOR_MFR_MICRON:
 		st_micron_set_default_init(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index b4ed9acbef63..9af3a701de95 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -175,6 +175,7 @@ extern const struct spi_nor_manufacturer spi_nor_fujitsu;
 extern const struct spi_nor_manufacturer spi_nor_gigadevice;
 extern const struct spi_nor_manufacturer spi_nor_intel;
 extern const struct spi_nor_manufacturer spi_nor_issi;
+extern const struct spi_nor_manufacturer spi_nor_macronix;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
new file mode 100644
index 000000000000..1ae609c44676
--- /dev/null
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static int
+mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
+			    const struct sfdp_parameter_header *bfpt_header,
+			    const struct sfdp_bfpt *bfpt,
+			    struct spi_nor_flash_parameter *params)
+{
+	/*
+	 * MX25L25635F supports 4B opcodes but MX25L25635E does not.
+	 * Unfortunately, Macronix has re-used the same JEDEC ID for both
+	 * variants which prevents us from defining a new entry in the parts
+	 * table.
+	 * We need a way to differentiate MX25L25635E and MX25L25635F, and it
+	 * seems that the F version advertises support for Fast Read 4-4-4 in
+	 * its BFPT table.
+	 */
+	if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
+		nor->flags |= SNOR_F_4B_OPCODES;
+
+	return 0;
+}
+
+static struct spi_nor_fixups mx25l25635_fixups = {
+	.post_bfpt = mx25l25635_post_bfpt_fixups,
+};
+
+static const struct flash_info macronix_parts[] = {
+	/* Macronix */
+	{ "mx25l512e",   INFO(0xc22010, 0, 64 * 1024,   1, SECT_4K) },
+	{ "mx25l2005a",  INFO(0xc22012, 0, 64 * 1024,   4, SECT_4K) },
+	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
+	{ "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, 0) },
+	{ "mx25l1606e",  INFO(0xc22015, 0, 64 * 1024,  32, SECT_4K) },
+	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, SECT_4K) },
+	{ "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
+	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
+	{ "mx25u2033e",  INFO(0xc22532, 0, 64 * 1024,   4, SECT_4K) },
+	{ "mx25u3235f",	 INFO(0xc22536, 0, 64 * 1024,  64,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+	{ "mx25u4035",   INFO(0xc22533, 0, 64 * 1024,   8, SECT_4K) },
+	{ "mx25u8035",   INFO(0xc22534, 0, 64 * 1024,  16, SECT_4K) },
+	{ "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
+	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
+	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
+	{ "mx25r3235f",  INFO(0xc22816, 0, 64 * 1024,  64,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+	{ "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
+			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
+		.fixups = &mx25l25635_fixups },
+	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
+			      SECT_4K | SPI_NOR_4B_OPCODES) },
+	{ "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024,
+			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			      SPI_NOR_4B_OPCODES) },
+	{ "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+	{ "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048,
+			      SPI_NOR_QUAD_READ) },
+};
+
+static void macronix_default_init(struct spi_nor *nor)
+{
+	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+	nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
+}
+
+static const struct spi_nor_fixups macronix_fixups = {
+	.default_init = macronix_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_macronix = {
+	.name = "macronix",
+	.parts = macronix_parts,
+	.nparts = ARRAY_SIZE(macronix_parts),
+	.fixups = &macronix_fixups,
+};
-- 
2.23.0

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

* [PATCH 16/23] mtd: spi-nor: Move Spansion bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (13 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 14/23] mtd: spi-nor: Move Macronix " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 15/23] mtd: spi-nor: Move Micron/ST " Tudor.Ambarus
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Spansion chips, and move the
Spansion definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile   |  1 +
 drivers/mtd/spi-nor/core.c     | 59 +--------------------
 drivers/mtd/spi-nor/core.h     |  1 +
 drivers/mtd/spi-nor/spansion.c | 95 ++++++++++++++++++++++++++++++++++
 4 files changed, 98 insertions(+), 58 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/spansion.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index c7e5fb908bec..cb06ee50bf68 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -11,4 +11,5 @@ spi-nor-objs			+= intel.o
 spi-nor-objs			+= issi.o
 spi-nor-objs			+= macronix.o
 spi-nor-objs			+= micron-st.o
+spi-nor-objs			+= spansion.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 8d54dfe33cdc..448717543d1e 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2017,44 +2017,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Spansion/Cypress -- single (large) sector size only, at least
-	 * for the chips listed here (without boot sectors).
-	 */
-	{ "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64,
-			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
-	{ "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
-			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
-	{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
-	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
-	{ "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
-			SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | USE_CLSR) },
-	{ "s25fs512s",  INFO6(0x010220, 0x4d0081, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
-	{ "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
-	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
-	{ "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
-	{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
-	{ "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_CLSR) },
-	{ "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, 0) },
-	{ "s25sl008a",  INFO(0x010213,      0,  64 * 1024,  16, 0) },
-	{ "s25sl016a",  INFO(0x010214,      0,  64 * 1024,  32, 0) },
-	{ "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64, 0) },
-	{ "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128, 0) },
-	{ "s25fl004k",  INFO(0xef4013,      0,  64 * 1024,   8, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "s25fl008k",  INFO(0xef4014,      0,  64 * 1024,  16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "s25fl016k",  INFO(0xef4015,      0,  64 * 1024,  32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "s25fl064k",  INFO(0xef4017,      0,  64 * 1024, 128, SECT_4K) },
-	{ "s25fl116k",  INFO(0x014015,      0,  64 * 1024,  32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "s25fl132k",  INFO(0x014016,      0,  64 * 1024,  64, SECT_4K) },
-	{ "s25fl164k",  INFO(0x014017,      0,  64 * 1024, 128, SECT_4K) },
-	{ "s25fl204k",  INFO(0x014013,      0,  64 * 1024,   8, SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "s25fl208k",  INFO(0x014014,      0,  64 * 1024,  16, SECT_4K | SPI_NOR_DUAL_READ) },
-	{ "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ "s25fl256l",  INFO(0x016019,      0,  64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-
 	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
 	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8, SECT_4K | SST_WRITE) },
 	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
@@ -2173,6 +2135,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_macronix,
 	&spi_nor_micron,
 	&spi_nor_st,
+	&spi_nor_spansion,
 };
 
 static const struct flash_info *
@@ -3106,17 +3069,6 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
 	spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
 }
 
-static void spansion_post_sfdp_fixups(struct spi_nor *nor)
-{
-	if (nor->params.size <= SZ_16M)
-		return;
-
-	nor->flags |= SNOR_F_4B_OPCODES;
-	/* No small sector erase for 4-byte command set */
-	nor->erase_opcode = SPINOR_OP_SE;
-	nor->mtd.erasesize = nor->info->sector_size;
-}
-
 static void s3an_post_sfdp_fixups(struct spi_nor *nor)
 {
 	nor->params.setup = s3an_nor_setup;
@@ -3134,15 +3086,6 @@ static void s3an_post_sfdp_fixups(struct spi_nor *nor)
  */
 static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
 {
-	switch (JEDEC_MFR(nor->info)) {
-	case SNOR_MFR_SPANSION:
-		spansion_post_sfdp_fixups(nor);
-		break;
-
-	default:
-		break;
-	}
-
 	if (nor->info->flags & SPI_S3AN)
 		s3an_post_sfdp_fixups(nor);
 
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 7e3ec8e4ef34..8e45617578f3 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -178,6 +178,7 @@ extern const struct spi_nor_manufacturer spi_nor_issi;
 extern const struct spi_nor_manufacturer spi_nor_macronix;
 extern const struct spi_nor_manufacturer spi_nor_micron;
 extern const struct spi_nor_manufacturer spi_nor_st;
+extern const struct spi_nor_manufacturer spi_nor_spansion;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
new file mode 100644
index 000000000000..16683983a20e
--- /dev/null
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info spansion_parts[] = {
+	/* Spansion/Cypress -- single (large) sector size only, at least
+	 * for the chips listed here (without boot sectors).
+	 */
+	{ "s25sl032p",  INFO(0x010215, 0x4d00,  64 * 1024,  64,
+			     SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25sl064p",  INFO(0x010216, 0x4d00,  64 * 1024, 128,
+			     SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl128s0", INFO6(0x012018, 0x4d0080, 256 * 1024, 64,
+			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			      USE_CLSR) },
+	{ "s25fl128s1", INFO6(0x012018, 0x4d0180, 64 * 1024, 256,
+			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			      USE_CLSR) },
+	{ "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, USE_CLSR) },
+	{ "s25fl256s1", INFO(0x010219, 0x4d01,  64 * 1024, 512,
+			     SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     USE_CLSR) },
+	{ "s25fl512s",  INFO6(0x010220, 0x4d0080, 256 * 1024, 256,
+			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			      SPI_NOR_HAS_LOCK | USE_CLSR) },
+	{ "s25fs512s",  INFO6(0x010220, 0x4d0081, 256 * 1024, 256,
+			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			      USE_CLSR) },
+	{ "s70fl01gs",  INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
+	{ "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024,  64, 0) },
+	{ "s25sl12801", INFO(0x012018, 0x0301,  64 * 1024, 256, 0) },
+	{ "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024,  64,
+			     SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     USE_CLSR) },
+	{ "s25fl129p1", INFO(0x012018, 0x4d01,  64 * 1024, 256,
+			     SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     USE_CLSR) },
+	{ "s25sl004a",  INFO(0x010212,      0,  64 * 1024,   8, 0) },
+	{ "s25sl008a",  INFO(0x010213,      0,  64 * 1024,  16, 0) },
+	{ "s25sl016a",  INFO(0x010214,      0,  64 * 1024,  32, 0) },
+	{ "s25sl032a",  INFO(0x010215,      0,  64 * 1024,  64, 0) },
+	{ "s25sl064a",  INFO(0x010216,      0,  64 * 1024, 128, 0) },
+	{ "s25fl004k",  INFO(0xef4013,      0,  64 * 1024,   8,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl008k",  INFO(0xef4014,      0,  64 * 1024,  16,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl016k",  INFO(0xef4015,      0,  64 * 1024,  32,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl064k",  INFO(0xef4017,      0,  64 * 1024, 128, SECT_4K) },
+	{ "s25fl116k",  INFO(0x014015,      0,  64 * 1024,  32,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "s25fl132k",  INFO(0x014016,      0,  64 * 1024,  64, SECT_4K) },
+	{ "s25fl164k",  INFO(0x014017,      0,  64 * 1024, 128, SECT_4K) },
+	{ "s25fl204k",  INFO(0x014013,      0,  64 * 1024,   8,
+			     SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "s25fl208k",  INFO(0x014014,      0,  64 * 1024,  16,
+			     SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "s25fl064l",  INFO(0x016017,      0,  64 * 1024, 128,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     SPI_NOR_4B_OPCODES) },
+	{ "s25fl128l",  INFO(0x016018,      0,  64 * 1024, 256,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     SPI_NOR_4B_OPCODES) },
+	{ "s25fl256l",  INFO(0x016019,      0,  64 * 1024, 512,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			     SPI_NOR_4B_OPCODES) },
+};
+
+static void spansion_post_sfdp_fixups(struct spi_nor *nor)
+{
+	if (nor->params.size <= SZ_16M)
+		return;
+
+	nor->flags |= SNOR_F_4B_OPCODES;
+	/* No small sector erase for 4-byte command set */
+	nor->erase_opcode = SPINOR_OP_SE;
+	nor->mtd.erasesize = nor->info->sector_size;
+}
+
+static const struct spi_nor_fixups spansion_fixups = {
+	.post_sfdp = spansion_post_sfdp_fixups,
+};
+
+const struct spi_nor_manufacturer spi_nor_spansion = {
+	.name = "spansion",
+	.parts = spansion_parts,
+	.nparts = ARRAY_SIZE(spansion_parts),
+	.fixups = &spansion_fixups,
+};
-- 
2.23.0

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

* [PATCH 15/23] mtd: spi-nor: Move Micron/ST bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (14 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 16/23] mtd: spi-nor: Move Spansion " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 18/23] mtd: spi-nor: Move Winbond " Tudor.Ambarus
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Micron/ST chips, and move the
Micron/ST definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile    |   1 +
 drivers/mtd/spi-nor/core.c      |  98 +-----------------------
 drivers/mtd/spi-nor/core.h      |   2 +
 drivers/mtd/spi-nor/micron-st.c | 129 ++++++++++++++++++++++++++++++++
 4 files changed, 134 insertions(+), 96 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/micron-st.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index c94798987801..c7e5fb908bec 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -10,4 +10,5 @@ spi-nor-objs			+= gigadevice.o
 spi-nor-objs			+= intel.o
 spi-nor-objs			+= issi.o
 spi-nor-objs			+= macronix.o
+spi-nor-objs			+= micron-st.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 9d0e0fc5af45..8d54dfe33cdc 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2017,53 +2017,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Micron <--> ST Micro */
-	{ "n25q016a",	 INFO(0x20bb15, 0, 64 * 1024,   32, SECT_4K | SPI_NOR_QUAD_READ) },
-	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
-	{ "n25q032a",	 INFO(0x20bb16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
-	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, SECT_4K | SPI_NOR_QUAD_READ) },
-	{ "n25q064a",    INFO(0x20bb17, 0, 64 * 1024,  128, SECT_4K | SPI_NOR_QUAD_READ) },
-	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SECT_4K |
-			      USE_FSR | SPI_NOR_QUAD_READ) },
-	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SECT_4K |
-			      USE_FSR | SPI_NOR_QUAD_READ) },
-	{ "mt25ql256a",  INFO6(0x20ba19, 0x104400, 64 * 1024,  512,
-			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K |
-			      USE_FSR | SPI_NOR_DUAL_READ |
-			      SPI_NOR_QUAD_READ) },
-	{ "mt25qu256a",  INFO6(0x20bb19, 0x104400, 64 * 1024,  512,
-			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512, SECT_4K |
-			      USE_FSR | SPI_NOR_QUAD_READ) },
-	{ "mt25ql512a",  INFO6(0x20ba20, 0x104400, 64 * 1024, 1024,
-			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
-	{ "mt25qu512a",  INFO6(0x20bb20, 0x104400, 64 * 1024, 1024,
-			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
-			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
-	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K |
-			      USE_FSR | SPI_NOR_QUAD_READ) },
-	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
-	{ "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
-	{ "mt25ql02g",   INFO(0x20ba22, 0, 64 * 1024, 4096,
-			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
-			      NO_CHIP_ERASE) },
-	{ "mt25qu02g",   INFO(0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
-
-	/* Micron */
-	{
-		"mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
-			SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
-			SPI_NOR_4B_OPCODES)
-	},
-	{ "mt35xu02g",  INFO(0x2c5b1c, 0, 128 * 1024, 2048,
-			     SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
-			     SPI_NOR_4B_OPCODES) },
-
 	/* Spansion/Cypress -- single (large) sector size only, at least
 	 * for the chips listed here (without boot sectors).
 	 */
@@ -2121,42 +2074,6 @@ static const struct flash_info spi_nor_ids[] = {
 			      SPI_NOR_DUAL_READ) },
 	{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 
-	/* ST Microelectronics -- newer production may have feature updates */
-	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2, 0) },
-	{ "m25p10",  INFO(0x202011,  0,  32 * 1024,   4, 0) },
-	{ "m25p20",  INFO(0x202012,  0,  64 * 1024,   4, 0) },
-	{ "m25p40",  INFO(0x202013,  0,  64 * 1024,   8, 0) },
-	{ "m25p80",  INFO(0x202014,  0,  64 * 1024,  16, 0) },
-	{ "m25p16",  INFO(0x202015,  0,  64 * 1024,  32, 0) },
-	{ "m25p32",  INFO(0x202016,  0,  64 * 1024,  64, 0) },
-	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, 0) },
-	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64, 0) },
-
-	{ "m25p05-nonjedec",  INFO(0, 0,  32 * 1024,   2, 0) },
-	{ "m25p10-nonjedec",  INFO(0, 0,  32 * 1024,   4, 0) },
-	{ "m25p20-nonjedec",  INFO(0, 0,  64 * 1024,   4, 0) },
-	{ "m25p40-nonjedec",  INFO(0, 0,  64 * 1024,   8, 0) },
-	{ "m25p80-nonjedec",  INFO(0, 0,  64 * 1024,  16, 0) },
-	{ "m25p16-nonjedec",  INFO(0, 0,  64 * 1024,  32, 0) },
-	{ "m25p32-nonjedec",  INFO(0, 0,  64 * 1024,  64, 0) },
-	{ "m25p64-nonjedec",  INFO(0, 0,  64 * 1024, 128, 0) },
-	{ "m25p128-nonjedec", INFO(0, 0, 256 * 1024,  64, 0) },
-
-	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2, 0) },
-	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, 0) },
-	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, 0) },
-
-	{ "m25pe20", INFO(0x208012,  0, 64 * 1024,  4,       0) },
-	{ "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
-	{ "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
-
-	{ "m25px16",    INFO(0x207115,  0, 64 * 1024, 32, SECT_4K) },
-	{ "m25px32",    INFO(0x207116,  0, 64 * 1024, 64, SECT_4K) },
-	{ "m25px32-s0", INFO(0x207316,  0, 64 * 1024, 64, SECT_4K) },
-	{ "m25px32-s1", INFO(0x206316,  0, 64 * 1024, 64, SECT_4K) },
-	{ "m25px64",    INFO(0x207117,  0, 64 * 1024, 128, 0) },
-	{ "m25px80",    INFO(0x207114,  0, 64 * 1024, 16, 0) },
-
 	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
 	{ "w25x05", INFO(0xef3010, 0, 64 * 1024,  1,  SECT_4K) },
 	{ "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
@@ -2254,6 +2171,8 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_intel,
 	&spi_nor_issi,
 	&spi_nor_macronix,
+	&spi_nor_micron,
+	&spi_nor_st,
 };
 
 static const struct flash_info *
@@ -3038,14 +2957,6 @@ static void sst_set_default_init(struct spi_nor *nor)
 	nor->flags |= SNOR_F_HAS_LOCK;
 }
 
-static void st_micron_set_default_init(struct spi_nor *nor)
-{
-	nor->flags |= SNOR_F_HAS_LOCK;
-	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
-	nor->params.quad_enable = NULL;
-	nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
-}
-
 static void winbond_set_default_init(struct spi_nor *nor)
 {
 	nor->params.set_4byte = winbond_set_4byte;
@@ -3060,11 +2971,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 {
 	/* Init flash parameters based on MFR */
 	switch (JEDEC_MFR(nor->info)) {
-	case SNOR_MFR_ST:
-	case SNOR_MFR_MICRON:
-		st_micron_set_default_init(nor);
-		break;
-
 	case SNOR_MFR_SST:
 		sst_set_default_init(nor);
 		break;
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 9af3a701de95..7e3ec8e4ef34 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -176,6 +176,8 @@ extern const struct spi_nor_manufacturer spi_nor_gigadevice;
 extern const struct spi_nor_manufacturer spi_nor_intel;
 extern const struct spi_nor_manufacturer spi_nor_issi;
 extern const struct spi_nor_manufacturer spi_nor_macronix;
+extern const struct spi_nor_manufacturer spi_nor_micron;
+extern const struct spi_nor_manufacturer spi_nor_st;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
new file mode 100644
index 000000000000..8017ca58b3a5
--- /dev/null
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info micron_parts[] = {
+	{ "mt35xu512aba", INFO(0x2c5b1a, 0, 128 * 1024, 512,
+			       SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+			       SPI_NOR_4B_OPCODES) },
+	{ "mt35xu02g", INFO(0x2c5b1c, 0, 128 * 1024, 2048,
+			    SECT_4K | USE_FSR | SPI_NOR_OCTAL_READ |
+			    SPI_NOR_4B_OPCODES) },
+};
+
+static const struct flash_info st_parts[] = {
+	{ "n25q016a",	 INFO(0x20bb15, 0, 64 * 1024,   32,
+			      SECT_4K | SPI_NOR_QUAD_READ) },
+	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64,
+			      SPI_NOR_QUAD_READ) },
+	{ "n25q032a",	 INFO(0x20bb16, 0, 64 * 1024,   64,
+			      SPI_NOR_QUAD_READ) },
+	{ "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128,
+			      SECT_4K | SPI_NOR_QUAD_READ) },
+	{ "n25q064a",    INFO(0x20bb17, 0, 64 * 1024,  128,
+			      SECT_4K | SPI_NOR_QUAD_READ) },
+	{ "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+	{ "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+	{ "mt25ql256a",  INFO6(0x20ba19, 0x104400, 64 * 1024,  512,
+			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+	{ "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K |
+			      USE_FSR | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+	{ "mt25qu256a",  INFO6(0x20bb19, 0x104400, 64 * 1024,  512,
+			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+	{ "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+	{ "mt25ql512a",  INFO6(0x20ba20, 0x104400, 64 * 1024, 1024,
+			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+	{ "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+	{ "mt25qu512a",  INFO6(0x20bb20, 0x104400, 64 * 1024, 1024,
+			       SECT_4K | USE_FSR | SPI_NOR_DUAL_READ |
+			       SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
+	{ "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+	{ "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+			      NO_CHIP_ERASE) },
+	{ "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+			      NO_CHIP_ERASE) },
+	{ "mt25ql02g",   INFO(0x20ba22, 0, 64 * 1024, 4096,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+			      NO_CHIP_ERASE) },
+	{ "mt25qu02g",   INFO(0x20bb22, 0, 64 * 1024, 4096,
+			      SECT_4K | USE_FSR | SPI_NOR_QUAD_READ |
+			      NO_CHIP_ERASE) },
+
+	{ "m25p05",  INFO(0x202010,  0,  32 * 1024,   2, 0) },
+	{ "m25p10",  INFO(0x202011,  0,  32 * 1024,   4, 0) },
+	{ "m25p20",  INFO(0x202012,  0,  64 * 1024,   4, 0) },
+	{ "m25p40",  INFO(0x202013,  0,  64 * 1024,   8, 0) },
+	{ "m25p80",  INFO(0x202014,  0,  64 * 1024,  16, 0) },
+	{ "m25p16",  INFO(0x202015,  0,  64 * 1024,  32, 0) },
+	{ "m25p32",  INFO(0x202016,  0,  64 * 1024,  64, 0) },
+	{ "m25p64",  INFO(0x202017,  0,  64 * 1024, 128, 0) },
+	{ "m25p128", INFO(0x202018,  0, 256 * 1024,  64, 0) },
+
+	{ "m25p05-nonjedec",  INFO(0, 0,  32 * 1024,   2, 0) },
+	{ "m25p10-nonjedec",  INFO(0, 0,  32 * 1024,   4, 0) },
+	{ "m25p20-nonjedec",  INFO(0, 0,  64 * 1024,   4, 0) },
+	{ "m25p40-nonjedec",  INFO(0, 0,  64 * 1024,   8, 0) },
+	{ "m25p80-nonjedec",  INFO(0, 0,  64 * 1024,  16, 0) },
+	{ "m25p16-nonjedec",  INFO(0, 0,  64 * 1024,  32, 0) },
+	{ "m25p32-nonjedec",  INFO(0, 0,  64 * 1024,  64, 0) },
+	{ "m25p64-nonjedec",  INFO(0, 0,  64 * 1024, 128, 0) },
+	{ "m25p128-nonjedec", INFO(0, 0, 256 * 1024,  64, 0) },
+
+	{ "m45pe10", INFO(0x204011,  0, 64 * 1024,    2, 0) },
+	{ "m45pe80", INFO(0x204014,  0, 64 * 1024,   16, 0) },
+	{ "m45pe16", INFO(0x204015,  0, 64 * 1024,   32, 0) },
+
+	{ "m25pe20", INFO(0x208012,  0, 64 * 1024,  4,       0) },
+	{ "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
+	{ "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
+
+	{ "m25px16",    INFO(0x207115,  0, 64 * 1024, 32, SECT_4K) },
+	{ "m25px32",    INFO(0x207116,  0, 64 * 1024, 64, SECT_4K) },
+	{ "m25px32-s0", INFO(0x207316,  0, 64 * 1024, 64, SECT_4K) },
+	{ "m25px32-s1", INFO(0x206316,  0, 64 * 1024, 64, SECT_4K) },
+	{ "m25px64",    INFO(0x207117,  0, 64 * 1024, 128, 0) },
+	{ "m25px80",    INFO(0x207114,  0, 64 * 1024, 16, 0) },
+};
+
+static void micron_st_default_init(struct spi_nor *nor)
+{
+	nor->flags |= SNOR_F_HAS_LOCK;
+	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
+	nor->params.quad_enable = NULL;
+	nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
+}
+
+static const struct spi_nor_fixups micron_st_fixups = {
+	.default_init = micron_st_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_micron = {
+	.name = "micron",
+	.parts = micron_parts,
+	.nparts = ARRAY_SIZE(micron_parts),
+	.fixups = &micron_st_fixups,
+};
+
+const struct spi_nor_manufacturer spi_nor_st = {
+	.name = "st",
+	.parts = st_parts,
+	.nparts = ARRAY_SIZE(st_parts),
+	.fixups = &micron_st_fixups,
+};
-- 
2.23.0

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

* [PATCH 18/23] mtd: spi-nor: Move Winbond bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (15 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 15/23] mtd: spi-nor: Move Micron/ST " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 17/23] mtd: spi-nor: Move SST " Tudor.Ambarus
                   ` (6 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Winbond chips, and move the
Winbond definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile  |   1 +
 drivers/mtd/spi-nor/core.c    | 115 +---------------------------------
 drivers/mtd/spi-nor/core.h    |   1 +
 drivers/mtd/spi-nor/winbond.c | 113 +++++++++++++++++++++++++++++++++
 4 files changed, 116 insertions(+), 114 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/winbond.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index ef7afc654a15..33b6f834a14f 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -13,4 +13,5 @@ spi-nor-objs			+= macronix.o
 spi-nor-objs			+= micron-st.o
 spi-nor-objs			+= spansion.o
 spi-nor-objs			+= sst.o
+spi-nor-objs			+= winbond.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 9ff0b09887b4..c99f063b0781 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -487,38 +487,6 @@ int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
 	return ret;
 }
 
-/**
- * winbond_set_4byte() - Set 4-byte address mode for Winbond flashes.
- * @nor:	pointer to 'struct spi_nor'.
- * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
- *		address mode.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int winbond_set_4byte(struct spi_nor *nor, bool enable)
-{
-	int ret;
-
-	ret = spi_nor_en4_ex4_set_4byte(nor, enable);
-	if (ret || enable)
-		return ret;
-
-	/*
-	 * On Winbond W25Q256FV, leaving 4byte mode causes the Extended Address
-	 * Register to be set to 1, so all 3-byte-address reads come from the
-	 * second 16M. We must clear the register to enable normal behavior.
-	 */
-	ret = spi_nor_write_enable(nor);
-	if (ret)
-		return ret;
-
-	ret = spi_nor_write_ear(nor, 0);
-	if (ret)
-		return ret;
-
-	return spi_nor_write_disable(nor);
-}
-
 /**
  * spi_nor_xread_sr() - Read the Status Register on S3AN flashes.
  * @nor:	pointer to 'struct spi_nor'.
@@ -2017,73 +1985,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
-	{ "w25x05", INFO(0xef3010, 0, 64 * 1024,  1,  SECT_4K) },
-	{ "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
-	{ "w25x20", INFO(0xef3012, 0, 64 * 1024,  4,  SECT_4K) },
-	{ "w25x40", INFO(0xef3013, 0, 64 * 1024,  8,  SECT_4K) },
-	{ "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, SECT_4K) },
-	{ "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
-	{
-		"w25q16dw", INFO(0xef6015, 0, 64 * 1024,  32,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{ "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
-	{
-		"w25q16jv-im/jm", INFO(0xef7015, 0, 64 * 1024,  32,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{ "w25q20cl", INFO(0xef4012, 0, 64 * 1024,  4, SECT_4K) },
-	{ "w25q20bw", INFO(0xef5012, 0, 64 * 1024,  4, SECT_4K) },
-	{ "w25q20ew", INFO(0xef6012, 0, 64 * 1024,  4, SECT_4K) },
-	{ "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
-	{
-		"w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"w25q32jv", INFO(0xef7016, 0, 64 * 1024,  64,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"w25q32jwm", INFO(0xef8016, 0, 64 * 1024,  64,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
-	{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
-	{
-		"w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{
-		"w25q128jv", INFO(0xef7018, 0, 64 * 1024, 256,
-			SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
-	},
-	{ "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
-	{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
-	{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
-	{ "w25q256", INFO(0xef4019, 0, 64 * 1024, 512,
-			  SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
-			  SPI_NOR_4B_OPCODES) },
-	{ "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512,
-			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512,
-			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024,
-			SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) },
-
 	/* Catalyst / On Semiconductor -- non-JEDEC */
 	{ "cat25c11", CAT25_INFO(  16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
 	{ "cat25c03", CAT25_INFO(  32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
@@ -2118,6 +2019,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_st,
 	&spi_nor_spansion,
 	&spi_nor_sst,
+	&spi_nor_winbond,
 };
 
 static const struct flash_info *
@@ -2811,11 +2713,6 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return nor->params.setup(nor, hwcaps);
 }
 
-static void winbond_set_default_init(struct spi_nor *nor)
-{
-	nor->params.set_4byte = winbond_set_4byte;
-}
-
 /**
  * spi_nor_manufacturer_init_params() - Initialize the flash's parameters and
  * settings based on MFR register and ->default_init() hook.
@@ -2823,16 +2720,6 @@ static void winbond_set_default_init(struct spi_nor *nor)
  */
 static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 {
-	/* Init flash parameters based on MFR */
-	switch (JEDEC_MFR(nor->info)) {
-	case SNOR_MFR_WINBOND:
-		winbond_set_default_init(nor);
-		break;
-
-	default:
-		break;
-	}
-
 	if (nor->manufacturer && nor->manufacturer->fixups &&
 	    nor->manufacturer->fixups->default_init)
 		nor->manufacturer->fixups->default_init(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 7bc0f6a15b36..01e0b8e2b191 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -180,6 +180,7 @@ extern const struct spi_nor_manufacturer spi_nor_micron;
 extern const struct spi_nor_manufacturer spi_nor_st;
 extern const struct spi_nor_manufacturer spi_nor_spansion;
 extern const struct spi_nor_manufacturer spi_nor_sst;
+extern const struct spi_nor_manufacturer spi_nor_winbond;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
new file mode 100644
index 000000000000..1e77dffbf729
--- /dev/null
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -0,0 +1,113 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info winbond_parts[] = {
+	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
+	{ "w25x05", INFO(0xef3010, 0, 64 * 1024,  1,  SECT_4K) },
+	{ "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
+	{ "w25x20", INFO(0xef3012, 0, 64 * 1024,  4,  SECT_4K) },
+	{ "w25x40", INFO(0xef3013, 0, 64 * 1024,  8,  SECT_4K) },
+	{ "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, SECT_4K) },
+	{ "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
+	{ "w25q16dw", INFO(0xef6015, 0, 64 * 1024,  32,
+			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
+	{ "w25q16jv-im/jm", INFO(0xef7015, 0, 64 * 1024,  32,
+				 SECT_4K | SPI_NOR_DUAL_READ |
+				 SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK |
+				 SPI_NOR_HAS_TB) },
+	{ "w25q20cl", INFO(0xef4012, 0, 64 * 1024,  4, SECT_4K) },
+	{ "w25q20bw", INFO(0xef5012, 0, 64 * 1024,  4, SECT_4K) },
+	{ "w25q20ew", INFO(0xef6012, 0, 64 * 1024,  4, SECT_4K) },
+	{ "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
+	{ "w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64,
+			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "w25q32jv", INFO(0xef7016, 0, 64 * 1024,  64,
+			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
+	},
+	{ "w25q32jwm", INFO(0xef8016, 0, 64 * 1024,  64,
+			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			    SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
+	{ "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+	{ "w25q64dw", INFO(0xef6017, 0, 64 * 1024, 128,
+			   SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			   SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "w25q128fw", INFO(0xef6018, 0, 64 * 1024, 256,
+			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			    SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "w25q128jv", INFO(0xef7018, 0, 64 * 1024, 256,
+			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			    SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) },
+	{ "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
+	{ "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
+	{ "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
+	{ "w25q256", INFO(0xef4019, 0, 64 * 1024, 512,
+			  SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
+			  SPI_NOR_4B_OPCODES) },
+	{ "w25q256jvm", INFO(0xef7019, 0, 64 * 1024, 512,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "w25q256jw", INFO(0xef6019, 0, 64 * 1024, 512,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "w25m512jv", INFO(0xef7119, 0, 64 * 1024, 1024,
+			    SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_DUAL_READ) },
+};
+
+/**
+ * winbond_set_4byte() - Set 4-byte address mode for Winbond flashes.
+ * @nor:	pointer to 'struct spi_nor'.
+ * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
+ *		address mode.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int winbond_set_4byte(struct spi_nor *nor, bool enable)
+{
+	int ret;
+
+	ret = spi_nor_en4_ex4_set_4byte(nor, enable);
+	if (ret || enable)
+		return ret;
+
+	/*
+	 * On Winbond W25Q256FV, leaving 4byte mode causes the Extended Address
+	 * Register to be set to 1, so all 3-byte-address reads come from the
+	 * second 16M. We must clear the register to enable normal behavior.
+	 */
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_ear(nor, 0);
+	if (ret)
+		return ret;
+
+	return spi_nor_write_disable(nor);
+}
+
+static void winbond_default_init(struct spi_nor *nor)
+{
+	nor->params.set_4byte = winbond_set_4byte;
+}
+
+static const struct spi_nor_fixups winbond_fixups = {
+	.default_init = winbond_default_init,
+};
+
+const struct spi_nor_manufacturer spi_nor_winbond = {
+	.name = "winbond",
+	.parts = winbond_parts,
+	.nparts = ARRAY_SIZE(winbond_parts),
+	.fixups = &winbond_fixups,
+};
+
-- 
2.23.0

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

* [PATCH 17/23] mtd: spi-nor: Move SST bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (16 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 18/23] mtd: spi-nor: Move Winbond " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 19/23] mtd: spi-nor: Move Catalyst " Tudor.Ambarus
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for SST chips, and move the
SST definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |   1 +
 drivers/mtd/spi-nor/core.c   | 123 +---------------------------
 drivers/mtd/spi-nor/core.h   |   1 +
 drivers/mtd/spi-nor/sst.c    | 151 +++++++++++++++++++++++++++++++++++
 4 files changed, 156 insertions(+), 120 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/sst.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index cb06ee50bf68..ef7afc654a15 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -12,4 +12,5 @@ spi-nor-objs			+= issi.o
 spi-nor-objs			+= macronix.o
 spi-nor-objs			+= micron-st.o
 spi-nor-objs			+= spansion.o
+spi-nor-objs			+= sst.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 448717543d1e..9ff0b09887b4 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2017,25 +2017,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
-	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8, SECT_4K | SST_WRITE) },
-	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
-	{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) },
-	{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) },
-	{ "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) },
-	{ "sst25wf512",  INFO(0xbf2501, 0, 64 * 1024,  1, SECT_4K | SST_WRITE) },
-	{ "sst25wf010",  INFO(0xbf2502, 0, 64 * 1024,  2, SECT_4K | SST_WRITE) },
-	{ "sst25wf020",  INFO(0xbf2503, 0, 64 * 1024,  4, SECT_4K | SST_WRITE) },
-	{ "sst25wf020a", INFO(0x621612, 0, 64 * 1024,  4, SECT_4K) },
-	{ "sst25wf040b", INFO(0x621613, 0, 64 * 1024,  8, SECT_4K) },
-	{ "sst25wf040",  INFO(0xbf2504, 0, 64 * 1024,  8, SECT_4K | SST_WRITE) },
-	{ "sst25wf080",  INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
-	{ "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32, SECT_4K |
-			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32, SECT_4K |
-			      SPI_NOR_DUAL_READ) },
-	{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-
 	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
 	{ "w25x05", INFO(0xef3010, 0, 64 * 1024,  1,  SECT_4K) },
 	{ "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
@@ -2136,6 +2117,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_micron,
 	&spi_nor_st,
 	&spi_nor_spansion,
+	&spi_nor_sst,
 };
 
 static const struct flash_info *
@@ -2236,92 +2218,6 @@ static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
 	return ret;
 }
 
-static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
-		size_t *retlen, const u_char *buf)
-{
-	struct spi_nor *nor = mtd_to_spi_nor(mtd);
-	size_t actual = 0;
-	int ret;
-
-	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
-
-	ret = spi_nor_lock_and_prep(nor);
-	if (ret)
-		return ret;
-
-	ret = spi_nor_write_enable(nor);
-	if (ret)
-		goto out;
-
-	nor->sst_write_second = false;
-
-	/* Start write from odd address. */
-	if (to % 2) {
-		nor->program_opcode = SPINOR_OP_BP;
-
-		/* write one byte. */
-		ret = spi_nor_write_data(nor, to, 1, buf);
-		if (ret < 0)
-			goto out;
-		WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
-		ret = spi_nor_wait_till_ready(nor);
-		if (ret)
-			goto out;
-
-		to++;
-		actual++;
-	}
-
-	/* Write out most of the data here. */
-	for (; actual < len - 1; actual += 2) {
-		nor->program_opcode = SPINOR_OP_AAI_WP;
-
-		/* write two bytes. */
-		ret = spi_nor_write_data(nor, to, 2, buf + actual);
-		if (ret < 0)
-			goto out;
-		WARN(ret != 2, "While writing 2 bytes written %i bytes\n", ret);
-		ret = spi_nor_wait_till_ready(nor);
-		if (ret)
-			goto out;
-		to += 2;
-		nor->sst_write_second = true;
-	}
-	nor->sst_write_second = false;
-
-	ret = spi_nor_write_disable(nor);
-	if (ret)
-		goto out;
-
-	ret = spi_nor_wait_till_ready(nor);
-	if (ret)
-		goto out;
-
-	/* Write out trailing byte if it exists. */
-	if (actual != len) {
-		ret = spi_nor_write_enable(nor);
-		if (ret)
-			goto out;
-
-		nor->program_opcode = SPINOR_OP_BP;
-		ret = spi_nor_write_data(nor, to, 1, buf + actual);
-		if (ret < 0)
-			goto out;
-		WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
-		ret = spi_nor_wait_till_ready(nor);
-		if (ret)
-			goto out;
-
-		actual += 1;
-
-		ret = spi_nor_write_disable(nor);
-	}
-out:
-	*retlen += actual;
-	spi_nor_unlock_and_unprep(nor);
-	return ret;
-}
-
 /*
  * Write an address range to the nor chip.  Data must be written in
  * FLASH_PAGESIZE chunks.  The address range may be any size provided
@@ -2915,11 +2811,6 @@ static int spi_nor_setup(struct spi_nor *nor,
 	return nor->params.setup(nor, hwcaps);
 }
 
-static void sst_set_default_init(struct spi_nor *nor)
-{
-	nor->flags |= SNOR_F_HAS_LOCK;
-}
-
 static void winbond_set_default_init(struct spi_nor *nor)
 {
 	nor->params.set_4byte = winbond_set_4byte;
@@ -2934,10 +2825,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
 {
 	/* Init flash parameters based on MFR */
 	switch (JEDEC_MFR(nor->info)) {
-	case SNOR_MFR_SST:
-		sst_set_default_init(nor);
-		break;
-
 	case SNOR_MFR_WINBOND:
 		winbond_set_default_init(nor);
 		break;
@@ -3409,6 +3296,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	if (info->flags & SPI_NOR_HAS_LOCK)
 		nor->flags |= SNOR_F_HAS_LOCK;
 
+	mtd->_write = spi_nor_write;
+
 	/* Init flash parameters based on flash_info struct and SFDP */
 	spi_nor_init_params(nor);
 
@@ -3429,12 +3318,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 		mtd->_is_locked = spi_nor_is_locked;
 	}
 
-	/* sst nor chips use AAI word program */
-	if (info->flags & SST_WRITE)
-		mtd->_write = sst_write;
-	else
-		mtd->_write = spi_nor_write;
-
 	if (info->flags & USE_FSR)
 		nor->flags |= SNOR_F_USE_FSR;
 	if (info->flags & SPI_NOR_HAS_TB) {
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 8e45617578f3..7bc0f6a15b36 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -179,6 +179,7 @@ extern const struct spi_nor_manufacturer spi_nor_macronix;
 extern const struct spi_nor_manufacturer spi_nor_micron;
 extern const struct spi_nor_manufacturer spi_nor_st;
 extern const struct spi_nor_manufacturer spi_nor_spansion;
+extern const struct spi_nor_manufacturer spi_nor_sst;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/sst.c b/drivers/mtd/spi-nor/sst.c
new file mode 100644
index 000000000000..e0af6d25d573
--- /dev/null
+++ b/drivers/mtd/spi-nor/sst.c
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info sst_parts[] = {
+	/* SST -- large erase sizes are "overlays", "sectors" are 4K */
+	{ "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024,  8,
+			      SECT_4K | SST_WRITE) },
+	{ "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16,
+			      SECT_4K | SST_WRITE) },
+	{ "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32,
+			      SECT_4K | SST_WRITE) },
+	{ "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64,
+			      SECT_4K | SST_WRITE) },
+	{ "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) },
+	{ "sst25wf512",  INFO(0xbf2501, 0, 64 * 1024,  1,
+			      SECT_4K | SST_WRITE) },
+	{ "sst25wf010",  INFO(0xbf2502, 0, 64 * 1024,  2,
+			      SECT_4K | SST_WRITE) },
+	{ "sst25wf020",  INFO(0xbf2503, 0, 64 * 1024,  4,
+			      SECT_4K | SST_WRITE) },
+	{ "sst25wf020a", INFO(0x621612, 0, 64 * 1024,  4, SECT_4K) },
+	{ "sst25wf040b", INFO(0x621613, 0, 64 * 1024,  8, SECT_4K) },
+	{ "sst25wf040",  INFO(0xbf2504, 0, 64 * 1024,  8,
+			      SECT_4K | SST_WRITE) },
+	{ "sst25wf080",  INFO(0xbf2505, 0, 64 * 1024, 16,
+			      SECT_4K | SST_WRITE) },
+	{ "sst26wf016b", INFO(0xbf2651, 0, 64 * 1024, 32,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+	{ "sst26vf016b", INFO(0xbf2641, 0, 64 * 1024, 32,
+			      SECT_4K | SPI_NOR_DUAL_READ) },
+	{ "sst26vf064b", INFO(0xbf2643, 0, 64 * 1024, 128,
+			      SECT_4K | SPI_NOR_DUAL_READ |
+			      SPI_NOR_QUAD_READ) },
+};
+
+static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+		     size_t *retlen, const u_char *buf)
+{
+	struct spi_nor *nor = mtd_to_spi_nor(mtd);
+	size_t actual = 0;
+	int ret;
+
+	dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
+
+	ret = spi_nor_lock_and_prep(nor);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		goto out;
+
+	nor->sst_write_second = false;
+
+	/* Start write from odd address. */
+	if (to % 2) {
+		nor->program_opcode = SPINOR_OP_BP;
+
+		/* write one byte. */
+		ret = spi_nor_write_data(nor, to, 1, buf);
+		if (ret < 0)
+			goto out;
+		WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
+		ret = spi_nor_wait_till_ready(nor);
+		if (ret)
+			goto out;
+
+		to++;
+		actual++;
+	}
+
+	/* Write out most of the data here. */
+	for (; actual < len - 1; actual += 2) {
+		nor->program_opcode = SPINOR_OP_AAI_WP;
+
+		/* write two bytes. */
+		ret = spi_nor_write_data(nor, to, 2, buf + actual);
+		if (ret < 0)
+			goto out;
+		WARN(ret != 2, "While writing 2 bytes written %i bytes\n", ret);
+		ret = spi_nor_wait_till_ready(nor);
+		if (ret)
+			goto out;
+		to += 2;
+		nor->sst_write_second = true;
+	}
+	nor->sst_write_second = false;
+
+	ret = spi_nor_write_disable(nor);
+	if (ret)
+		goto out;
+
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret)
+		goto out;
+
+	/* Write out trailing byte if it exists. */
+	if (actual != len) {
+		ret = spi_nor_write_enable(nor);
+		if (ret)
+			goto out;
+
+		nor->program_opcode = SPINOR_OP_BP;
+		ret = spi_nor_write_data(nor, to, 1, buf + actual);
+		if (ret < 0)
+			goto out;
+		WARN(ret != 1, "While writing 1 byte written %i bytes\n", ret);
+		ret = spi_nor_wait_till_ready(nor);
+		if (ret)
+			goto out;
+
+		actual += 1;
+
+		ret = spi_nor_write_disable(nor);
+	}
+out:
+	*retlen += actual;
+	spi_nor_unlock_and_unprep(nor);
+	return ret;
+}
+
+static void sst_default_init(struct spi_nor *nor)
+{
+	nor->flags |= SNOR_F_HAS_LOCK;
+}
+
+static void sst_post_sfdp_fixups(struct spi_nor *nor)
+{
+	if (nor->info->flags & SST_WRITE)
+		nor->mtd._write = sst_write;
+}
+
+static const struct spi_nor_fixups sst_fixups = {
+	.default_init = sst_default_init,
+	.post_sfdp = sst_post_sfdp_fixups,
+};
+
+const struct spi_nor_manufacturer spi_nor_sst = {
+	.name = "sst",
+	.parts = sst_parts,
+	.nparts = ARRAY_SIZE(sst_parts),
+	.fixups = &sst_fixups,
+};
-- 
2.23.0

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

* [PATCH 19/23] mtd: spi-nor: Move Catalyst bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (17 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 17/23] mtd: spi-nor: Move SST " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 21/23] mtd: spi-nor: Move XMC " Tudor.Ambarus
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Catalyst chips, and move the
Catalyst definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile   |  1 +
 drivers/mtd/spi-nor/catalyst.c | 29 +++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.c     |  8 +-------
 drivers/mtd/spi-nor/core.h     |  1 +
 4 files changed, 32 insertions(+), 7 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/catalyst.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 33b6f834a14f..cd8d95b727c9 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -2,6 +2,7 @@
 
 spi-nor-objs			:= core.o sfdp.o
 spi-nor-objs			+= atmel.o
+spi-nor-objs			+= catalyst.o
 spi-nor-objs			+= eon.o
 spi-nor-objs			+= esmt.o
 spi-nor-objs			+= everspin.o
diff --git a/drivers/mtd/spi-nor/catalyst.c b/drivers/mtd/spi-nor/catalyst.c
new file mode 100644
index 000000000000..011b83e99e95
--- /dev/null
+++ b/drivers/mtd/spi-nor/catalyst.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info catalyst_parts[] = {
+	/* Catalyst / On Semiconductor -- non-JEDEC */
+	{ "cat25c11", CAT25_INFO(16, 8, 16, 1,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "cat25c03", CAT25_INFO(32, 8, 16, 2,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "cat25c09", CAT25_INFO(128, 8, 32, 2,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "cat25c17", CAT25_INFO(256, 8, 32, 2,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+	{ "cat25128", CAT25_INFO(2048, 8, 64, 2,
+				 SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+};
+
+const struct spi_nor_manufacturer spi_nor_catalyst = {
+	.name = "catalyst",
+	.parts = catalyst_parts,
+	.nparts = ARRAY_SIZE(catalyst_parts),
+};
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index c99f063b0781..1776fb8eb66b 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1985,13 +1985,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Catalyst / On Semiconductor -- non-JEDEC */
-	{ "cat25c11", CAT25_INFO(  16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-	{ "cat25c03", CAT25_INFO(  32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-	{ "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-	{ "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-	{ "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
-
 	/* Xilinx S3AN Internal Flash */
 	{ "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
 	{ "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
@@ -2007,6 +2000,7 @@ static const struct flash_info spi_nor_ids[] = {
 
 static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_atmel,
+	&spi_nor_catalyst,
 	&spi_nor_eon,
 	&spi_nor_esmt,
 	&spi_nor_everspin,
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 01e0b8e2b191..9eb46900bc72 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -168,6 +168,7 @@ struct spi_nor_manufacturer {
 
 /* Manufacturer drivers. */
 extern const struct spi_nor_manufacturer spi_nor_atmel;
+extern const struct spi_nor_manufacturer spi_nor_catalyst;
 extern const struct spi_nor_manufacturer spi_nor_eon;
 extern const struct spi_nor_manufacturer spi_nor_esmt;
 extern const struct spi_nor_manufacturer spi_nor_everspin;
-- 
2.23.0

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

* [PATCH 20/23] mtd: spi-nor: Move Xilinx bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (19 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 21/23] mtd: spi-nor: Move XMC " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 22/23] mtd: spi-nor: Get rid of the now empty spi_nor_ids[] table Tudor.Ambarus
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for Xilinx chips, and move the
Xilinx definitions outside of core.c.

While at it, remove the SPI_S3AN flag which is now useless.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |  1 +
 drivers/mtd/spi-nor/core.c   | 76 +----------------------------
 drivers/mtd/spi-nor/core.h   | 13 +----
 drivers/mtd/spi-nor/xilinx.c | 94 ++++++++++++++++++++++++++++++++++++
 4 files changed, 98 insertions(+), 86 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/xilinx.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index cd8d95b727c9..fa03513dd160 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -15,4 +15,5 @@ spi-nor-objs			+= micron-st.o
 spi-nor-objs			+= spansion.o
 spi-nor-objs			+= sst.o
 spi-nor-objs			+= winbond.o
+spi-nor-objs			+= xilinx.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 1776fb8eb66b..3e9f6bafa01b 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1117,26 +1117,6 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor)
 	mutex_unlock(&nor->lock);
 }
 
-/*
- * This code converts an address to the Default Address Mode, that has non
- * power of two page sizes. We must support this mode because it is the default
- * mode supported by Xilinx tools, it can access the whole flash area and
- * changing over to the Power-of-two mode is irreversible and corrupts the
- * original data.
- * Addr can safely be unsigned int, the biggest S3AN device is smaller than
- * 4 MiB.
- */
-static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr)
-{
-	u32 offset, page;
-
-	offset = addr % nor->page_size;
-	page = addr / nor->page_size;
-	page <<= (nor->page_size > 512) ? 10 : 9;
-
-	return page | offset;
-}
-
 static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr)
 {
 	if (!nor->params.convert_addr)
@@ -1985,13 +1965,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* Xilinx S3AN Internal Flash */
-	{ "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
-	{ "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
-	{ "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
-	{ "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
-	{ "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
-
 	/* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */
 	{ "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
@@ -2014,6 +1987,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_spansion,
 	&spi_nor_sst,
 	&spi_nor_winbond,
+	&spi_nor_xilinx,
 };
 
 static const struct flash_info *
@@ -2199,46 +2173,6 @@ static int spi_nor_check(struct spi_nor *nor)
 	return 0;
 }
 
-static int s3an_nor_setup(struct spi_nor *nor,
-			  const struct spi_nor_hwcaps *hwcaps)
-{
-	int ret;
-
-	ret = spi_nor_xread_sr(nor, nor->bouncebuf);
-	if (ret)
-		return ret;
-
-	nor->erase_opcode = SPINOR_OP_XSE;
-	nor->program_opcode = SPINOR_OP_XPP;
-	nor->read_opcode = SPINOR_OP_READ;
-	nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
-
-	/*
-	 * This flashes have a page size of 264 or 528 bytes (known as
-	 * Default addressing mode). It can be changed to a more standard
-	 * Power of two mode where the page size is 256/512. This comes
-	 * with a price: there is 3% less of space, the data is corrupted
-	 * and the page size cannot be changed back to default addressing
-	 * mode.
-	 *
-	 * The current addressing mode can be read from the XRDSR register
-	 * and should not be changed, because is a destructive operation.
-	 */
-	if (nor->bouncebuf[0] & XSR_PAGESIZE) {
-		/* Flash in Power of 2 mode */
-		nor->page_size = (nor->page_size == 264) ? 256 : 512;
-		nor->mtd.writebufsize = nor->page_size;
-		nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
-		nor->mtd.erasesize = 8 * nor->page_size;
-	} else {
-		/* Flash in Default addressing mode */
-		nor->params.convert_addr = s3an_convert_addr;
-		nor->mtd.erasesize = nor->info->sector_size;
-	}
-
-	return 0;
-}
-
 static void
 spi_nor_set_read_settings(struct spi_nor_read_command *read,
 			  u8 num_mode_clocks,
@@ -2837,11 +2771,6 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
 	spi_nor_init_uniform_erase_map(map, erase_mask, params->size);
 }
 
-static void s3an_post_sfdp_fixups(struct spi_nor *nor)
-{
-	nor->params.setup = s3an_nor_setup;
-}
-
 /**
  * spi_nor_post_sfdp_fixups() - Updates the flash's parameters and settings
  * after SFDP has been parsed (is also called for SPI NORs that do not
@@ -2854,9 +2783,6 @@ static void s3an_post_sfdp_fixups(struct spi_nor *nor)
  */
 static void spi_nor_post_sfdp_fixups(struct spi_nor *nor)
 {
-	if (nor->info->flags & SPI_S3AN)
-		s3an_post_sfdp_fixups(nor);
-
 	if (nor->manufacturer && nor->manufacturer->fixups &&
 	    nor->manufacturer->fixups->post_sfdp)
 		nor->manufacturer->fixups->post_sfdp(nor);
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 9eb46900bc72..abd5332afaf5 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -73,16 +73,6 @@ struct flash_info {
 #define SPI_NOR_XSR_RDY		BIT(10)	/*
 					 * S3AN flashes have specific opcode to
 					 * read the status register.
-					 * Flags SPI_NOR_XSR_RDY and SPI_S3AN
-					 * use the same bit as one implies the
-					 * other, but we will get rid of
-					 * SPI_S3AN soon.
-					 */
-#define	SPI_S3AN		BIT(10)	/*
-					 * Xilinx Spartan 3AN In-System Flash
-					 * (MFR cannot be used for probing
-					 * because it has the same value as
-					 * ATMEL flashes)
 					 */
 #define SPI_NOR_4B_OPCODES	BIT(11)	/*
 					 * Use dedicated 4byte address op codes
@@ -150,7 +140,7 @@ struct flash_info {
 		.n_sectors = (_n_sectors),				\
 		.page_size = _page_size,				\
 		.addr_width = 3,					\
-		.flags = SPI_NOR_NO_FR | SPI_S3AN,
+		.flags = SPI_NOR_NO_FR | SPI_NOR_XSR_RDY,
 
 /**
  * struct spi_nor_manufacturer - SPI NOR manufacturer object
@@ -182,6 +172,7 @@ extern const struct spi_nor_manufacturer spi_nor_st;
 extern const struct spi_nor_manufacturer spi_nor_spansion;
 extern const struct spi_nor_manufacturer spi_nor_sst;
 extern const struct spi_nor_manufacturer spi_nor_winbond;
+extern const struct spi_nor_manufacturer spi_nor_xilinx;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
new file mode 100644
index 000000000000..fcf635d89f65
--- /dev/null
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info xilinx_parts[] = {
+	/* Xilinx S3AN Internal Flash */
+	{ "3S50AN", S3AN_INFO(0x1f2200, 64, 264) },
+	{ "3S200AN", S3AN_INFO(0x1f2400, 256, 264) },
+	{ "3S400AN", S3AN_INFO(0x1f2400, 256, 264) },
+	{ "3S700AN", S3AN_INFO(0x1f2500, 512, 264) },
+	{ "3S1400AN", S3AN_INFO(0x1f2600, 512, 528) },
+};
+
+/*
+ * This code converts an address to the Default Address Mode, that has non
+ * power of two page sizes. We must support this mode because it is the default
+ * mode supported by Xilinx tools, it can access the whole flash area and
+ * changing over to the Power-of-two mode is irreversible and corrupts the
+ * original data.
+ * Addr can safely be unsigned int, the biggest S3AN device is smaller than
+ * 4 MiB.
+ */
+static u32 s3an_convert_addr(struct spi_nor *nor, u32 addr)
+{
+	u32 offset, page;
+
+	offset = addr % nor->page_size;
+	page = addr / nor->page_size;
+	page <<= (nor->page_size > 512) ? 10 : 9;
+
+	return page | offset;
+}
+
+static int xilinx_nor_setup(struct spi_nor *nor,
+			    const struct spi_nor_hwcaps *hwcaps)
+{
+	int ret;
+
+	ret = spi_nor_xread_sr(nor, nor->bouncebuf);
+	if (ret)
+		return ret;
+
+	nor->erase_opcode = SPINOR_OP_XSE;
+	nor->program_opcode = SPINOR_OP_XPP;
+	nor->read_opcode = SPINOR_OP_READ;
+	nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
+
+	/*
+	 * This flashes have a page size of 264 or 528 bytes (known as
+	 * Default addressing mode). It can be changed to a more standard
+	 * Power of two mode where the page size is 256/512. This comes
+	 * with a price: there is 3% less of space, the data is corrupted
+	 * and the page size cannot be changed back to default addressing
+	 * mode.
+	 *
+	 * The current addressing mode can be read from the XRDSR register
+	 * and should not be changed, because is a destructive operation.
+	 */
+	if (nor->bouncebuf[0] & XSR_PAGESIZE) {
+		/* Flash in Power of 2 mode */
+		nor->page_size = (nor->page_size == 264) ? 256 : 512;
+		nor->mtd.writebufsize = nor->page_size;
+		nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
+		nor->mtd.erasesize = 8 * nor->page_size;
+	} else {
+		/* Flash in Default addressing mode */
+		nor->params.convert_addr = s3an_convert_addr;
+		nor->mtd.erasesize = nor->info->sector_size;
+	}
+
+	return 0;
+}
+
+static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
+{
+	nor->params.setup = xilinx_nor_setup;
+}
+
+static const struct spi_nor_fixups xilinx_fixups = {
+	.post_sfdp = xilinx_post_sfdp_fixups,
+};
+
+const struct spi_nor_manufacturer spi_nor_xilinx = {
+	.name = "xilinx",
+	.parts = xilinx_parts,
+	.nparts = ARRAY_SIZE(xilinx_parts),
+	.fixups = &xilinx_fixups,
+};
-- 
2.23.0

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

* [PATCH 21/23] mtd: spi-nor: Move XMC bits out of core.c
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (18 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 19/23] mtd: spi-nor: Move Catalyst " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 20/23] mtd: spi-nor: Move Xilinx " Tudor.Ambarus
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

Create a SPI NOR manufacturer driver for XMC chips, and move the
XMC definitions outside of core.c.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/Makefile |  1 +
 drivers/mtd/spi-nor/core.c   |  4 +---
 drivers/mtd/spi-nor/core.h   |  1 +
 drivers/mtd/spi-nor/xmc.c    | 23 +++++++++++++++++++++++
 4 files changed, 26 insertions(+), 3 deletions(-)
 create mode 100644 drivers/mtd/spi-nor/xmc.c

diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index fa03513dd160..7ddb742de1fe 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -16,4 +16,5 @@ spi-nor-objs			+= spansion.o
 spi-nor-objs			+= sst.o
 spi-nor-objs			+= winbond.o
 spi-nor-objs			+= xilinx.o
+spi-nor-objs			+= xmc.o
 obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 3e9f6bafa01b..f4178cd65c45 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1965,9 +1965,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
  * old entries may be missing 4K flag.
  */
 static const struct flash_info spi_nor_ids[] = {
-	/* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */
-	{ "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
-	{ "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
 	{ },
 };
 
@@ -1988,6 +1985,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_sst,
 	&spi_nor_winbond,
 	&spi_nor_xilinx,
+	&spi_nor_xmc,
 };
 
 static const struct flash_info *
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index abd5332afaf5..3541a84c03d8 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -173,6 +173,7 @@ extern const struct spi_nor_manufacturer spi_nor_spansion;
 extern const struct spi_nor_manufacturer spi_nor_sst;
 extern const struct spi_nor_manufacturer spi_nor_winbond;
 extern const struct spi_nor_manufacturer spi_nor_xilinx;
+extern const struct spi_nor_manufacturer spi_nor_xmc;
 
 int spi_nor_write_enable(struct spi_nor *nor);
 int spi_nor_write_disable(struct spi_nor *nor);
diff --git a/drivers/mtd/spi-nor/xmc.c b/drivers/mtd/spi-nor/xmc.c
new file mode 100644
index 000000000000..2c7773b68993
--- /dev/null
+++ b/drivers/mtd/spi-nor/xmc.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ */
+
+#include <linux/mtd/spi-nor.h>
+
+#include "core.h"
+
+static const struct flash_info xmc_parts[] = {
+	/* XMC (Wuhan Xinxin Semiconductor Manufacturing Corp.) */
+	{ "XM25QH64A", INFO(0x207017, 0, 64 * 1024, 128,
+			    SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+	{ "XM25QH128A", INFO(0x207018, 0, 64 * 1024, 256,
+			     SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+};
+
+const struct spi_nor_manufacturer spi_nor_xmc = {
+	.name = "xmc",
+	.parts = xmc_parts,
+	.nparts = ARRAY_SIZE(xmc_parts),
+};
-- 
2.23.0

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

* [PATCH 22/23] mtd: spi-nor: Get rid of the now empty spi_nor_ids[] table
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (20 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 20/23] mtd: spi-nor: Move Xilinx " Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-02 18:07 ` [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h Tudor.Ambarus
  2020-03-03  7:15 ` [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Joel Stanley
  23 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Boris Brezillon <bbrezillon@kernel.org>

All entries have been moved to manufacturer drivers. Get rid of this
empty table.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/core.c | 25 -------------------------
 1 file changed, 25 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index f4178cd65c45..a2e1917b608d 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1953,21 +1953,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
 	return 0;
 }
 
-/* NOTE: double check command sets and memory organization when you add
- * more nor chips.  This current list focusses on newer chips, which
- * have been converging on command sets which including JEDEC ID.
- *
- * All newly added entries should describe *hardware* and should use SECT_4K
- * (or SECT_4K_PMC) if hardware supports erasing 4 KiB sectors. For usage
- * scenarios excluding small sectors there is config option that can be
- * disabled: CONFIG_MTD_SPI_NOR_USE_4K_SECTORS.
- * For historical (and compatibility) reasons (before we got above config) some
- * old entries may be missing 4K flag.
- */
-static const struct flash_info spi_nor_ids[] = {
-	{ },
-};
-
 static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_atmel,
 	&spi_nor_catalyst,
@@ -2037,11 +2022,6 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
 		}
 	}
 
-	info = spi_nor_search_part_by_id(spi_nor_ids,
-					 ARRAY_SIZE(spi_nor_ids) - 1, id);
-	if (info)
-		return info;
-
 	dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
 		SPI_NOR_MAX_ID_LEN, id);
 	return ERR_PTR(-ENODEV);
@@ -2952,11 +2932,6 @@ static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
 {
 	unsigned int i, j;
 
-	for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) {
-		if (!strcmp(name, spi_nor_ids[i].name))
-			return &spi_nor_ids[i];
-	}
-
 	for (i = 0; i < ARRAY_SIZE(manufacturers); i++) {
 		for (j = 0; j < manufacturers[i]->nparts; j++) {
 			if (!strcmp(name, manufacturers[i]->parts[j].name)) {
-- 
2.23.0

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

* [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (21 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 22/23] mtd: spi-nor: Get rid of the now empty spi_nor_ids[] table Tudor.Ambarus
@ 2020-03-02 18:07 ` Tudor.Ambarus
  2020-03-07 14:49   ` Boris Brezillon
  2020-03-13  8:13   ` Vignesh Raghavendra
  2020-03-03  7:15 ` [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Joel Stanley
  23 siblings, 2 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-02 18:07 UTC (permalink / raw)
  To: bbrezillon, vigneshr, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel, Tudor.Ambarus

From: Tudor Ambarus <tudor.ambarus@microchip.com>

The SPI NOR controllers drivers must not be able to use structures that
are meant just for the SPI NOR core.

struct spi_nor_flash_parameter is filled at run-time with info gathered
from flash_info, manufacturer and sfdp data. struct spi_nor_flash_parameter
should be opaque to the SPI NOR controller drivers, make sure it is.

spi_nor_option_flags, spi_nor_read_command, spi_nor_pp_command,
spi_nor_read_command_index and spi_nor_pp_command_index are defined for the
core use, make sure they are opaque to the SPI NOR controller drivers.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
 drivers/mtd/spi-nor/core.c       |  86 ++++++----
 drivers/mtd/spi-nor/core.h       | 214 +++++++++++++++++++++++++
 drivers/mtd/spi-nor/gigadevice.c |   2 +-
 drivers/mtd/spi-nor/issi.c       |   2 +-
 drivers/mtd/spi-nor/macronix.c   |   4 +-
 drivers/mtd/spi-nor/micron-st.c  |   4 +-
 drivers/mtd/spi-nor/sfdp.c       |  10 ++
 drivers/mtd/spi-nor/spansion.c   |   2 +-
 drivers/mtd/spi-nor/winbond.c    |   2 +-
 drivers/mtd/spi-nor/xilinx.c     |   4 +-
 include/linux/mtd/spi-nor.h      | 259 +------------------------------
 11 files changed, 294 insertions(+), 295 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index a2e1917b608d..860dac1dff90 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -802,7 +802,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
 		ret = spi_nor_read_cr(nor, &sr_cr[1]);
 		if (ret)
 			return ret;
-	} else if (nor->params.quad_enable) {
+	} else if (nor->params->quad_enable) {
 		/*
 		 * If the Status Register 2 Read command (35h) is not
 		 * supported, we should at least be sure we don't
@@ -810,7 +810,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
 		 *
 		 * We can safely assume that when the Quad Enable method is
 		 * set, the value of the QE bit is one, as a consequence of the
-		 * nor->params.quad_enable() call.
+		 * nor->params->quad_enable() call.
 		 *
 		 * We can safely assume that the Quad Enable bit is present in
 		 * the Status Register 2 at BIT(1). According to the JESD216
@@ -1075,6 +1075,11 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
 				      ARRAY_SIZE(spi_nor_3to4_erase));
 }
 
+static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
+{
+	return !!nor->params->erase_map.uniform_erase_type;
+}
+
 static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
 {
 	nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
@@ -1082,7 +1087,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
 	nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
 
 	if (!spi_nor_has_uniform_erase(nor)) {
-		struct spi_nor_erase_map *map = &nor->params.erase_map;
+		struct spi_nor_erase_map *map = &nor->params->erase_map;
 		struct spi_nor_erase_type *erase;
 		int i;
 
@@ -1119,10 +1124,10 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor)
 
 static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr)
 {
-	if (!nor->params.convert_addr)
+	if (!nor->params->convert_addr)
 		return addr;
 
-	return nor->params.convert_addr(nor, addr);
+	return nor->params->convert_addr(nor, addr);
 }
 
 /*
@@ -1227,6 +1232,16 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
 	return NULL;
 }
 
+static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region)
+{
+	return region->offset & SNOR_LAST_REGION;
+}
+
+static u64 spi_nor_region_end(const struct spi_nor_erase_region *region)
+{
+	return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
+}
+
 /**
  * spi_nor_region_next() - get the next spi nor region
  * @region:	pointer to a structure that describes a SPI NOR erase region
@@ -1331,7 +1346,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
 				       struct list_head *erase_list,
 				       u64 addr, u32 len)
 {
-	const struct spi_nor_erase_map *map = &nor->params.erase_map;
+	const struct spi_nor_erase_map *map = &nor->params->erase_map;
 	const struct spi_nor_erase_type *erase, *prev_erase = NULL;
 	struct spi_nor_erase_region *region;
 	struct spi_nor_erase_command *cmd = NULL;
@@ -1817,7 +1832,7 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	if (ret)
 		return ret;
 
-	ret = nor->params.locking_ops->lock(nor, ofs, len);
+	ret = nor->params->locking_ops->lock(nor, ofs, len);
 
 	spi_nor_unlock_and_unprep(nor);
 	return ret;
@@ -1832,7 +1847,7 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	if (ret)
 		return ret;
 
-	ret = nor->params.locking_ops->unlock(nor, ofs, len);
+	ret = nor->params->locking_ops->unlock(nor, ofs, len);
 
 	spi_nor_unlock_and_unprep(nor);
 	return ret;
@@ -1847,7 +1862,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	if (ret)
 		return ret;
 
-	ret = nor->params.locking_ops->is_locked(nor, ofs, len);
+	ret = nor->params->locking_ops->is_locked(nor, ofs, len);
 
 	spi_nor_unlock_and_unprep(nor);
 	return ret;
@@ -2312,7 +2327,7 @@ static int spi_nor_spimem_check_pp(struct spi_nor *nor,
 static void
 spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
 {
-	struct spi_nor_flash_parameter *params =  &nor->params;
+	struct spi_nor_flash_parameter *params = nor->params;
 	unsigned int cap;
 
 	/* DTR modes are not supported yet, mask them all. */
@@ -2411,7 +2426,7 @@ static int spi_nor_select_read(struct spi_nor *nor,
 	if (cmd < 0)
 		return -EINVAL;
 
-	read = &nor->params.reads[cmd];
+	read = &nor->params->reads[cmd];
 	nor->read_opcode = read->opcode;
 	nor->read_proto = read->proto;
 
@@ -2442,7 +2457,7 @@ static int spi_nor_select_pp(struct spi_nor *nor,
 	if (cmd < 0)
 		return -EINVAL;
 
-	pp = &nor->params.page_programs[cmd];
+	pp = &nor->params->page_programs[cmd];
 	nor->program_opcode = pp->opcode;
 	nor->write_proto = pp->proto;
 	return 0;
@@ -2503,7 +2518,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
 
 static int spi_nor_select_erase(struct spi_nor *nor)
 {
-	struct spi_nor_erase_map *map = &nor->params.erase_map;
+	struct spi_nor_erase_map *map = &nor->params->erase_map;
 	const struct spi_nor_erase_type *erase = NULL;
 	struct mtd_info *mtd = &nor->mtd;
 	u32 wanted_size = nor->info->sector_size;
@@ -2552,7 +2567,7 @@ static int spi_nor_select_erase(struct spi_nor *nor)
 static int spi_nor_default_setup(struct spi_nor *nor,
 				 const struct spi_nor_hwcaps *hwcaps)
 {
-	struct spi_nor_flash_parameter *params = &nor->params;
+	struct spi_nor_flash_parameter *params = nor->params;
 	u32 ignored_mask, shared_mask;
 	int err;
 
@@ -2613,10 +2628,10 @@ static int spi_nor_default_setup(struct spi_nor *nor,
 static int spi_nor_setup(struct spi_nor *nor,
 			 const struct spi_nor_hwcaps *hwcaps)
 {
-	if (!nor->params.setup)
+	if (!nor->params->setup)
 		return 0;
 
-	return nor->params.setup(nor, hwcaps);
+	return nor->params->setup(nor, hwcaps);
 }
 
 /**
@@ -2646,13 +2661,13 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
 {
 	struct spi_nor_flash_parameter sfdp_params;
 
-	memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params));
+	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
 
 	if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
 		nor->addr_width = 0;
 		nor->flags &= ~SNOR_F_4B_OPCODES;
 	} else {
-		memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
+		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
 	}
 }
 
@@ -2663,7 +2678,7 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
  */
 static void spi_nor_info_init_params(struct spi_nor *nor)
 {
-	struct spi_nor_flash_parameter *params = &nor->params;
+	struct spi_nor_flash_parameter *params = nor->params;
 	struct spi_nor_erase_map *map = &params->erase_map;
 	const struct flash_info *info = nor->info;
 	struct device_node *np = spi_nor_get_flash_node(nor);
@@ -2782,8 +2797,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
 	 * NOR protection support. When locking_ops are not provided, we pick
 	 * the default ones.
 	 */
-	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops)
-		nor->params.locking_ops = &spi_nor_sr_locking_ops;
+	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
+		nor->params->locking_ops = &spi_nor_sr_locking_ops;
 }
 
 /**
@@ -2823,8 +2838,12 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
  * ->default_init() hook or the SFDP parser do not set specific params.
  *		spi_nor_late_init_params()
  */
-static void spi_nor_init_params(struct spi_nor *nor)
+static int spi_nor_init_params(struct spi_nor *nor)
 {
+	nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
+	if (!nor->params)
+		return -ENOMEM;
+
 	spi_nor_info_init_params(nor);
 
 	spi_nor_manufacturer_init_params(nor);
@@ -2836,6 +2855,8 @@ static void spi_nor_init_params(struct spi_nor *nor)
 	spi_nor_post_sfdp_fixups(nor);
 
 	spi_nor_late_init_params(nor);
+
+	return 0;
 }
 
 /**
@@ -2846,14 +2867,14 @@ static void spi_nor_init_params(struct spi_nor *nor)
  */
 static int spi_nor_quad_enable(struct spi_nor *nor)
 {
-	if (!nor->params.quad_enable)
+	if (!nor->params->quad_enable)
 		return 0;
 
 	if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
 	      spi_nor_get_protocol_width(nor->write_proto) == 4))
 		return 0;
 
-	return nor->params.quad_enable(nor);
+	return nor->params->quad_enable(nor);
 }
 
 /**
@@ -2868,7 +2889,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor)
 static int spi_nor_unlock_all(struct spi_nor *nor)
 {
 	if (nor->flags & SNOR_F_HAS_LOCK)
-		return spi_nor_unlock(&nor->mtd, 0, nor->params.size);
+		return spi_nor_unlock(&nor->mtd, 0, nor->params->size);
 
 	return 0;
 }
@@ -2899,7 +2920,7 @@ static int spi_nor_init(struct spi_nor *nor)
 		 */
 		WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
 			  "enabling reset hack; may not recover from unexpected reboots\n");
-		nor->params.set_4byte(nor, true);
+		nor->params->set_4byte(nor, true);
 	}
 
 	return 0;
@@ -2923,7 +2944,7 @@ void spi_nor_restore(struct spi_nor *nor)
 	/* restore the addressing mode */
 	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
 	    nor->flags & SNOR_F_BROKEN_RESET)
-		nor->params.set_4byte(nor, false);
+		nor->params->set_4byte(nor, false);
 }
 EXPORT_SYMBOL_GPL(spi_nor_restore);
 
@@ -3028,7 +3049,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	struct device *dev = nor->dev;
 	struct mtd_info *mtd = &nor->mtd;
 	struct device_node *np = spi_nor_get_flash_node(nor);
-	struct spi_nor_flash_parameter *params = &nor->params;
 	int ret;
 	int i;
 
@@ -3079,7 +3099,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	mtd->_write = spi_nor_write;
 
 	/* Init flash parameters based on flash_info struct and SFDP */
-	spi_nor_init_params(nor);
+	ret = spi_nor_init_params(nor);
+	if (ret)
+		return ret;
 
 	if (!mtd->name)
 		mtd->name = dev_name(dev);
@@ -3087,12 +3109,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 	mtd->type = MTD_NORFLASH;
 	mtd->writesize = 1;
 	mtd->flags = MTD_CAP_NORFLASH;
-	mtd->size = params->size;
+	mtd->size = nor->params->size;
 	mtd->_erase = spi_nor_erase;
 	mtd->_read = spi_nor_read;
 	mtd->_resume = spi_nor_resume;
 
-	if (nor->params.locking_ops) {
+	if (nor->params->locking_ops) {
 		mtd->_lock = spi_nor_lock;
 		mtd->_unlock = spi_nor_unlock;
 		mtd->_is_locked = spi_nor_is_locked;
@@ -3115,7 +3137,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 		mtd->flags |= MTD_NO_ERASE;
 
 	mtd->dev.parent = dev;
-	nor->page_size = params->page_size;
+	nor->page_size = nor->params->page_size;
 	mtd->writebufsize = nor->page_size;
 
 	if (of_property_read_bool(np, "broken-flash-reset"))
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 3541a84c03d8..7654b6f3b966 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -11,6 +11,220 @@
 
 #define SPI_NOR_MAX_ID_LEN	6
 
+enum spi_nor_option_flags {
+	SNOR_F_USE_FSR		= BIT(0),
+	SNOR_F_HAS_SR_TB	= BIT(1),
+	SNOR_F_NO_OP_CHIP_ERASE	= BIT(2),
+	SNOR_F_READY_XSR_RDY	= BIT(3),
+	SNOR_F_USE_CLSR		= BIT(4),
+	SNOR_F_BROKEN_RESET	= BIT(5),
+	SNOR_F_4B_OPCODES	= BIT(6),
+	SNOR_F_HAS_4BAIT	= BIT(7),
+	SNOR_F_HAS_LOCK		= BIT(8),
+	SNOR_F_HAS_16BIT_SR	= BIT(9),
+	SNOR_F_NO_READ_CR	= BIT(10),
+	SNOR_F_HAS_SR_TB_BIT6	= BIT(11),
+};
+
+struct spi_nor_read_command {
+	u8			num_mode_clocks;
+	u8			num_wait_states;
+	u8			opcode;
+	enum spi_nor_protocol	proto;
+};
+
+struct spi_nor_pp_command {
+	u8			opcode;
+	enum spi_nor_protocol	proto;
+};
+
+enum spi_nor_read_command_index {
+	SNOR_CMD_READ,
+	SNOR_CMD_READ_FAST,
+	SNOR_CMD_READ_1_1_1_DTR,
+
+	/* Dual SPI */
+	SNOR_CMD_READ_1_1_2,
+	SNOR_CMD_READ_1_2_2,
+	SNOR_CMD_READ_2_2_2,
+	SNOR_CMD_READ_1_2_2_DTR,
+
+	/* Quad SPI */
+	SNOR_CMD_READ_1_1_4,
+	SNOR_CMD_READ_1_4_4,
+	SNOR_CMD_READ_4_4_4,
+	SNOR_CMD_READ_1_4_4_DTR,
+
+	/* Octal SPI */
+	SNOR_CMD_READ_1_1_8,
+	SNOR_CMD_READ_1_8_8,
+	SNOR_CMD_READ_8_8_8,
+	SNOR_CMD_READ_1_8_8_DTR,
+
+	SNOR_CMD_READ_MAX
+};
+
+enum spi_nor_pp_command_index {
+	SNOR_CMD_PP,
+
+	/* Quad SPI */
+	SNOR_CMD_PP_1_1_4,
+	SNOR_CMD_PP_1_4_4,
+	SNOR_CMD_PP_4_4_4,
+
+	/* Octal SPI */
+	SNOR_CMD_PP_1_1_8,
+	SNOR_CMD_PP_1_8_8,
+	SNOR_CMD_PP_8_8_8,
+
+	SNOR_CMD_PP_MAX
+};
+
+/**
+ * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
+ * @size:		the size of the sector/block erased by the erase type.
+ *			JEDEC JESD216B imposes erase sizes to be a power of 2.
+ * @size_shift:		@size is a power of 2, the shift is stored in
+ *			@size_shift.
+ * @size_mask:		the size mask based on @size_shift.
+ * @opcode:		the SPI command op code to erase the sector/block.
+ * @idx:		Erase Type index as sorted in the Basic Flash Parameter
+ *			Table. It will be used to synchronize the supported
+ *			Erase Types with the ones identified in the SFDP
+ *			optional tables.
+ */
+struct spi_nor_erase_type {
+	u32	size;
+	u32	size_shift;
+	u32	size_mask;
+	u8	opcode;
+	u8	idx;
+};
+
+/**
+ * struct spi_nor_erase_command - Used for non-uniform erases
+ * The structure is used to describe a list of erase commands to be executed
+ * once we validate that the erase can be performed. The elements in the list
+ * are run-length encoded.
+ * @list:		for inclusion into the list of erase commands.
+ * @count:		how many times the same erase command should be
+ *			consecutively used.
+ * @size:		the size of the sector/block erased by the command.
+ * @opcode:		the SPI command op code to erase the sector/block.
+ */
+struct spi_nor_erase_command {
+	struct list_head	list;
+	u32			count;
+	u32			size;
+	u8			opcode;
+};
+
+/**
+ * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
+ * @offset:		the offset in the data array of erase region start.
+ *			LSB bits are used as a bitmask encoding flags to
+ *			determine if this region is overlaid, if this region is
+ *			the last in the SPI NOR flash memory and to indicate
+ *			all the supported erase commands inside this region.
+ *			The erase types are sorted in ascending order with the
+ *			smallest Erase Type size being at BIT(0).
+ * @size:		the size of the region in bytes.
+ */
+struct spi_nor_erase_region {
+	u64		offset;
+	u64		size;
+};
+
+#define SNOR_ERASE_TYPE_MAX	4
+#define SNOR_ERASE_TYPE_MASK	GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
+
+#define SNOR_LAST_REGION	BIT(4)
+#define SNOR_OVERLAID_REGION	BIT(5)
+
+#define SNOR_ERASE_FLAGS_MAX	6
+#define SNOR_ERASE_FLAGS_MASK	GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
+
+/**
+ * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
+ * @regions:		array of erase regions. The regions are consecutive in
+ *			address space. Walking through the regions is done
+ *			incrementally.
+ * @uniform_region:	a pre-allocated erase region for SPI NOR with a uniform
+ *			sector size (legacy implementation).
+ * @erase_type:		an array of erase types shared by all the regions.
+ *			The erase types are sorted in ascending order, with the
+ *			smallest Erase Type size being the first member in the
+ *			erase_type array.
+ * @uniform_erase_type:	bitmask encoding erase types that can erase the
+ *			entire memory. This member is completed at init by
+ *			uniform and non-uniform SPI NOR flash memories if they
+ *			support at least one erase type that can erase the
+ *			entire memory.
+ */
+struct spi_nor_erase_map {
+	struct spi_nor_erase_region	*regions;
+	struct spi_nor_erase_region	uniform_region;
+	struct spi_nor_erase_type	erase_type[SNOR_ERASE_TYPE_MAX];
+	u8				uniform_erase_type;
+};
+
+/**
+ * struct spi_nor_locking_ops - SPI NOR locking methods
+ * @lock:	lock a region of the SPI NOR.
+ * @unlock:	unlock a region of the SPI NOR.
+ * @is_locked:	check if a region of the SPI NOR is completely locked
+ */
+struct spi_nor_locking_ops {
+	int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+	int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+	int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
+};
+
+/**
+ * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
+ * Includes legacy flash parameters and settings that can be overwritten
+ * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
+ * Serial Flash Discoverable Parameters (SFDP) tables.
+ *
+ * @size:		the flash memory density in bytes.
+ * @page_size:		the page size of the SPI NOR flash memory.
+ * @hwcaps:		describes the read and page program hardware
+ *			capabilities.
+ * @reads:		read capabilities ordered by priority: the higher index
+ *                      in the array, the higher priority.
+ * @page_programs:	page program capabilities ordered by priority: the
+ *                      higher index in the array, the higher priority.
+ * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
+ *                      Table.
+ * @quad_enable:	enables SPI NOR quad mode.
+ * @set_4byte:		puts the SPI NOR in 4 byte addressing mode.
+ * @convert_addr:	converts an absolute address into something the flash
+ *                      will understand. Particularly useful when pagesize is
+ *                      not a power-of-2.
+ * @setup:              configures the SPI NOR memory. Useful for SPI NOR
+ *                      flashes that have peculiarities to the SPI NOR standard
+ *                      e.g. different opcodes, specific address calculation,
+ *                      page size, etc.
+ * @locking_ops:	SPI NOR locking methods.
+ */
+struct spi_nor_flash_parameter {
+	u64				size;
+	u32				page_size;
+
+	struct spi_nor_hwcaps		hwcaps;
+	struct spi_nor_read_command	reads[SNOR_CMD_READ_MAX];
+	struct spi_nor_pp_command	page_programs[SNOR_CMD_PP_MAX];
+
+	struct spi_nor_erase_map        erase_map;
+
+	int (*quad_enable)(struct spi_nor *nor);
+	int (*set_4byte)(struct spi_nor *nor, bool enable);
+	u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
+	int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
+
+	const struct spi_nor_locking_ops *locking_ops;
+};
+
 /**
  * struct spi_nor_fixups - SPI NOR fixup hooks
  * @default_init: called after default flash parameters init. Used to tweak
diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
index 7930e4490dab..447d84bb2128 100644
--- a/drivers/mtd/spi-nor/gigadevice.c
+++ b/drivers/mtd/spi-nor/gigadevice.c
@@ -16,7 +16,7 @@ static void gd25q256_default_init(struct spi_nor *nor)
 	 * indicate the quad_enable method for this case, we need
 	 * to set it in the default_init fixup hook.
 	 */
-	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
 }
 
 static struct spi_nor_fixups gd25q256_fixups = {
diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
index 3a1c34c41388..ffcb60e54a80 100644
--- a/drivers/mtd/spi-nor/issi.c
+++ b/drivers/mtd/spi-nor/issi.c
@@ -68,7 +68,7 @@ static const struct flash_info issi_parts[] = {
 
 static void issi_default_init(struct spi_nor *nor)
 {
-	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
+	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
 }
 
 static const struct spi_nor_fixups issi_fixups = {
diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
index 1ae609c44676..d73bd0363144 100644
--- a/drivers/mtd/spi-nor/macronix.c
+++ b/drivers/mtd/spi-nor/macronix.c
@@ -82,8 +82,8 @@ static const struct flash_info macronix_parts[] = {
 
 static void macronix_default_init(struct spi_nor *nor)
 {
-	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
-	nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
+	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
+	nor->params->set_4byte = spi_nor_en4_ex4_set_4byte;
 }
 
 static const struct spi_nor_fixups macronix_fixups = {
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index 8017ca58b3a5..5be817d2f27c 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -106,8 +106,8 @@ static void micron_st_default_init(struct spi_nor *nor)
 {
 	nor->flags |= SNOR_F_HAS_LOCK;
 	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
-	nor->params.quad_enable = NULL;
-	nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
+	nor->params->quad_enable = NULL;
+	nor->params->set_4byte = spi_nor_en4_ex4_wen_set_4byte;
 }
 
 static const struct spi_nor_fixups micron_st_fixups = {
diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
index b790c3ec871f..6829dc7e4f74 100644
--- a/drivers/mtd/spi-nor/sfdp.c
+++ b/drivers/mtd/spi-nor/sfdp.c
@@ -734,6 +734,16 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
 	return ret;
 }
 
+static void spi_nor_region_mark_end(struct spi_nor_erase_region *region)
+{
+	region->offset |= SNOR_LAST_REGION;
+}
+
+static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
+{
+	region->offset |= SNOR_OVERLAID_REGION;
+}
+
 /**
  * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid
  * @region:	pointer to a structure that describes a SPI NOR erase region
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 16683983a20e..6756202ace4b 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -74,7 +74,7 @@ static const struct flash_info spansion_parts[] = {
 
 static void spansion_post_sfdp_fixups(struct spi_nor *nor)
 {
-	if (nor->params.size <= SZ_16M)
+	if (nor->params->size <= SZ_16M)
 		return;
 
 	nor->flags |= SNOR_F_4B_OPCODES;
diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
index 1e77dffbf729..f15be50024d1 100644
--- a/drivers/mtd/spi-nor/winbond.c
+++ b/drivers/mtd/spi-nor/winbond.c
@@ -97,7 +97,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable)
 
 static void winbond_default_init(struct spi_nor *nor)
 {
-	nor->params.set_4byte = winbond_set_4byte;
+	nor->params->set_4byte = winbond_set_4byte;
 }
 
 static const struct spi_nor_fixups winbond_fixups = {
diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
index fcf635d89f65..1138bdbf4199 100644
--- a/drivers/mtd/spi-nor/xilinx.c
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -70,7 +70,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
 		nor->mtd.erasesize = 8 * nor->page_size;
 	} else {
 		/* Flash in Default addressing mode */
-		nor->params.convert_addr = s3an_convert_addr;
+		nor->params->convert_addr = s3an_convert_addr;
 		nor->mtd.erasesize = nor->info->sector_size;
 	}
 
@@ -79,7 +79,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
 
 static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
 {
-	nor->params.setup = xilinx_nor_setup;
+	nor->params->setup = xilinx_nor_setup;
 }
 
 static const struct spi_nor_fixups xilinx_fixups = {
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index dde2988a809e..d3d34c4eea48 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -227,110 +227,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto)
 	return spi_nor_get_protocol_data_nbits(proto);
 }
 
-enum spi_nor_option_flags {
-	SNOR_F_USE_FSR		= BIT(0),
-	SNOR_F_HAS_SR_TB	= BIT(1),
-	SNOR_F_NO_OP_CHIP_ERASE	= BIT(2),
-	SNOR_F_READY_XSR_RDY	= BIT(3),
-	SNOR_F_USE_CLSR		= BIT(4),
-	SNOR_F_BROKEN_RESET	= BIT(5),
-	SNOR_F_4B_OPCODES	= BIT(6),
-	SNOR_F_HAS_4BAIT	= BIT(7),
-	SNOR_F_HAS_LOCK		= BIT(8),
-	SNOR_F_HAS_16BIT_SR	= BIT(9),
-	SNOR_F_NO_READ_CR	= BIT(10),
-	SNOR_F_HAS_SR_TB_BIT6	= BIT(11),
-
-};
-
-/**
- * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
- * @size:		the size of the sector/block erased by the erase type.
- *			JEDEC JESD216B imposes erase sizes to be a power of 2.
- * @size_shift:		@size is a power of 2, the shift is stored in
- *			@size_shift.
- * @size_mask:		the size mask based on @size_shift.
- * @opcode:		the SPI command op code to erase the sector/block.
- * @idx:		Erase Type index as sorted in the Basic Flash Parameter
- *			Table. It will be used to synchronize the supported
- *			Erase Types with the ones identified in the SFDP
- *			optional tables.
- */
-struct spi_nor_erase_type {
-	u32	size;
-	u32	size_shift;
-	u32	size_mask;
-	u8	opcode;
-	u8	idx;
-};
-
-/**
- * struct spi_nor_erase_command - Used for non-uniform erases
- * The structure is used to describe a list of erase commands to be executed
- * once we validate that the erase can be performed. The elements in the list
- * are run-length encoded.
- * @list:		for inclusion into the list of erase commands.
- * @count:		how many times the same erase command should be
- *			consecutively used.
- * @size:		the size of the sector/block erased by the command.
- * @opcode:		the SPI command op code to erase the sector/block.
- */
-struct spi_nor_erase_command {
-	struct list_head	list;
-	u32			count;
-	u32			size;
-	u8			opcode;
-};
-
-/**
- * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
- * @offset:		the offset in the data array of erase region start.
- *			LSB bits are used as a bitmask encoding flags to
- *			determine if this region is overlaid, if this region is
- *			the last in the SPI NOR flash memory and to indicate
- *			all the supported erase commands inside this region.
- *			The erase types are sorted in ascending order with the
- *			smallest Erase Type size being at BIT(0).
- * @size:		the size of the region in bytes.
- */
-struct spi_nor_erase_region {
-	u64		offset;
-	u64		size;
-};
-
-#define SNOR_ERASE_TYPE_MAX	4
-#define SNOR_ERASE_TYPE_MASK	GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
-
-#define SNOR_LAST_REGION	BIT(4)
-#define SNOR_OVERLAID_REGION	BIT(5)
-
-#define SNOR_ERASE_FLAGS_MAX	6
-#define SNOR_ERASE_FLAGS_MASK	GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
-
-/**
- * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
- * @regions:		array of erase regions. The regions are consecutive in
- *			address space. Walking through the regions is done
- *			incrementally.
- * @uniform_region:	a pre-allocated erase region for SPI NOR with a uniform
- *			sector size (legacy implementation).
- * @erase_type:		an array of erase types shared by all the regions.
- *			The erase types are sorted in ascending order, with the
- *			smallest Erase Type size being the first member in the
- *			erase_type array.
- * @uniform_erase_type:	bitmask encoding erase types that can erase the
- *			entire memory. This member is completed at init by
- *			uniform and non-uniform SPI NOR flash memories if they
- *			support at least one erase type that can erase the
- *			entire memory.
- */
-struct spi_nor_erase_map {
-	struct spi_nor_erase_region	*regions;
-	struct spi_nor_erase_region	uniform_region;
-	struct spi_nor_erase_type	erase_type[SNOR_ERASE_TYPE_MAX];
-	u8				uniform_erase_type;
-};
-
 /**
  * struct spi_nor_hwcaps - Structure for describing the hardware capabilies
  * supported by the SPI controller (bus master).
@@ -406,61 +302,7 @@ struct spi_nor_hwcaps {
 #define SNOR_HWCAPS_ALL		(SNOR_HWCAPS_READ_MASK |	\
 				 SNOR_HWCAPS_PP_MASK)
 
-struct spi_nor_read_command {
-	u8			num_mode_clocks;
-	u8			num_wait_states;
-	u8			opcode;
-	enum spi_nor_protocol	proto;
-};
-
-struct spi_nor_pp_command {
-	u8			opcode;
-	enum spi_nor_protocol	proto;
-};
-
-enum spi_nor_read_command_index {
-	SNOR_CMD_READ,
-	SNOR_CMD_READ_FAST,
-	SNOR_CMD_READ_1_1_1_DTR,
-
-	/* Dual SPI */
-	SNOR_CMD_READ_1_1_2,
-	SNOR_CMD_READ_1_2_2,
-	SNOR_CMD_READ_2_2_2,
-	SNOR_CMD_READ_1_2_2_DTR,
-
-	/* Quad SPI */
-	SNOR_CMD_READ_1_1_4,
-	SNOR_CMD_READ_1_4_4,
-	SNOR_CMD_READ_4_4_4,
-	SNOR_CMD_READ_1_4_4_DTR,
-
-	/* Octal SPI */
-	SNOR_CMD_READ_1_1_8,
-	SNOR_CMD_READ_1_8_8,
-	SNOR_CMD_READ_8_8_8,
-	SNOR_CMD_READ_1_8_8_DTR,
-
-	SNOR_CMD_READ_MAX
-};
-
-enum spi_nor_pp_command_index {
-	SNOR_CMD_PP,
-
-	/* Quad SPI */
-	SNOR_CMD_PP_1_1_4,
-	SNOR_CMD_PP_1_4_4,
-	SNOR_CMD_PP_4_4_4,
-
-	/* Octal SPI */
-	SNOR_CMD_PP_1_1_8,
-	SNOR_CMD_PP_1_8_8,
-	SNOR_CMD_PP_8_8_8,
-
-	SNOR_CMD_PP_MAX
-};
-
-/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */
+/* Forward declaration that is used in 'struct spi_nor_controller_ops' */
 struct spi_nor;
 
 /**
@@ -491,74 +333,14 @@ struct spi_nor_controller_ops {
 	int (*erase)(struct spi_nor *nor, loff_t offs);
 };
 
-/**
- * struct spi_nor_locking_ops - SPI NOR locking methods
- * @lock:	lock a region of the SPI NOR.
- * @unlock:	unlock a region of the SPI NOR.
- * @is_locked:	check if a region of the SPI NOR is completely locked
- */
-struct spi_nor_locking_ops {
-	int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
-	int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
-	int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
-};
-
-/**
- * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
- * Includes legacy flash parameters and settings that can be overwritten
- * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
- * Serial Flash Discoverable Parameters (SFDP) tables.
- *
- * @size:		the flash memory density in bytes.
- * @page_size:		the page size of the SPI NOR flash memory.
- * @hwcaps:		describes the read and page program hardware
- *			capabilities.
- * @reads:		read capabilities ordered by priority: the higher index
- *                      in the array, the higher priority.
- * @page_programs:	page program capabilities ordered by priority: the
- *                      higher index in the array, the higher priority.
- * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
- *                      Table.
- * @quad_enable:	enables SPI NOR quad mode.
- * @set_4byte:		puts the SPI NOR in 4 byte addressing mode.
- * @convert_addr:	converts an absolute address into something the flash
- *                      will understand. Particularly useful when pagesize is
- *                      not a power-of-2.
- * @setup:              configures the SPI NOR memory. Useful for SPI NOR
- *                      flashes that have peculiarities to the SPI NOR standard
- *                      e.g. different opcodes, specific address calculation,
- *                      page size, etc.
- * @locking_ops:	SPI NOR locking methods.
- */
-struct spi_nor_flash_parameter {
-	u64				size;
-	u32				page_size;
-
-	struct spi_nor_hwcaps		hwcaps;
-	struct spi_nor_read_command	reads[SNOR_CMD_READ_MAX];
-	struct spi_nor_pp_command	page_programs[SNOR_CMD_PP_MAX];
 
-	struct spi_nor_erase_map        erase_map;
-
-	int (*quad_enable)(struct spi_nor *nor);
-	int (*set_4byte)(struct spi_nor *nor, bool enable);
-	u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
-	int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
-
-	const struct spi_nor_locking_ops *locking_ops;
-};
-
-/**
- * struct flash_info - Forward declaration of a structure used internally by
- *		       spi_nor_scan()
+/*
+ * Forward declarations that are used internally by the core and manufacturer
+ * drivers.
  */
 struct flash_info;
-
-/**
- * struct spi_nor_manufacturer - Forward declaration of a structure used
- * internally by the core and manufacturer drivers.
- */
 struct spi_nor_manufacturer;
+struct spi_nor_flash_parameter;
 
 /**
  * struct spi_nor - Structure for defining a the SPI NOR layer
@@ -613,7 +395,7 @@ struct spi_nor {
 
 	const struct spi_nor_controller_ops *controller_ops;
 
-	struct spi_nor_flash_parameter params;
+	struct spi_nor_flash_parameter *params;
 
 	struct {
 		struct spi_mem_dirmap_desc *rdesc;
@@ -623,35 +405,6 @@ struct spi_nor {
 	void *priv;
 };
 
-static u64 __maybe_unused
-spi_nor_region_is_last(const struct spi_nor_erase_region *region)
-{
-	return region->offset & SNOR_LAST_REGION;
-}
-
-static u64 __maybe_unused
-spi_nor_region_end(const struct spi_nor_erase_region *region)
-{
-	return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
-}
-
-static void __maybe_unused
-spi_nor_region_mark_end(struct spi_nor_erase_region *region)
-{
-	region->offset |= SNOR_LAST_REGION;
-}
-
-static void __maybe_unused
-spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
-{
-	region->offset |= SNOR_OVERLAID_REGION;
-}
-
-static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
-{
-	return !!nor->params.erase_map.uniform_erase_type;
-}
-
 static inline void spi_nor_set_flash_node(struct spi_nor *nor,
 					  struct device_node *np)
 {
-- 
2.23.0

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

* Re: [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core
  2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
                   ` (22 preceding siblings ...)
  2020-03-02 18:07 ` [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h Tudor.Ambarus
@ 2020-03-03  7:15 ` Joel Stanley
  2020-03-03  7:28   ` Tudor.Ambarus
  23 siblings, 1 reply; 39+ messages in thread
From: Joel Stanley @ 2020-03-03  7:15 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: Boris Brezillon, Vignesh Raghavendra, linux-mtd, Miquel Raynal,
	Richard Weinberger, Andrew Jeffery, Nicolas Ferre,
	Alexandre Belloni, Ludovic.Desroches, Matthias Brugger,
	Vladimir Zapolskiy, Michal Simek, ludovic.barre, john.garry,
	Thomas Gleixner, nishkadg.linux, Michael Walle, dinguyen,
	thor.thayer, Stephen Boyd, opensource, mika.westerberg,
	Kate Stewart, allison, jethro, info, alexander.sverdlin,
	rfontana, Linux Kernel Mailing List, linux-mediatek,
	linux-aspeed, Linux ARM

Hi Tudor,

On Mon, 2 Mar 2020 at 18:07, <Tudor.Ambarus@microchip.com> wrote:
>
> From: Tudor Ambarus <tudor.ambarus@microchip.com>
>
> Hello,
>
> This patch series is an attempt at getting all manufacturer specific
> quirks/code out of the core to make the core logic more readable and
> thus ease maintainance.

I tried to apply this to linus' tree (5.6-rc4) but it had a bunch of
conflicts. What did you base this on?

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

* Re: [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core
  2020-03-03  7:15 ` [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Joel Stanley
@ 2020-03-03  7:28   ` Tudor.Ambarus
  0 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-03  7:28 UTC (permalink / raw)
  To: joel
  Cc: bbrezillon, vigneshr, linux-mtd, miquel.raynal, richard, andrew,
	Nicolas.Ferre, alexandre.belloni, Ludovic.Desroches,
	matthias.bgg, vz, michal.simek, ludovic.barre, john.garry, tglx,
	nishkadg.linux, michael, dinguyen, thor.thayer, swboyd,
	opensource, mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel

On Tuesday, March 3, 2020 9:15:31 AM EET Joel Stanley wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> Hi Tudor,

Hi, Joel,

> 
> On Mon, 2 Mar 2020 at 18:07, <Tudor.Ambarus@microchip.com> wrote:
> > From: Tudor Ambarus <tudor.ambarus@microchip.com>
> > 
> > Hello,
> > 
> > This patch series is an attempt at getting all manufacturer specific
> > quirks/code out of the core to make the core logic more readable and
> > thus ease maintainance.
> 
> I tried to apply this to linus' tree (5.6-rc4) but it had a bunch of
> conflicts. What did you base this on?

T:      git git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git spi-
nor/next

Cheers,
ta


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

* Re: [PATCH 12/23] mtd: spi-nor: Move Intel bits out of core.c
  2020-03-02 18:07 ` [PATCH 12/23] mtd: spi-nor: Move Intel " Tudor.Ambarus
@ 2020-03-03 10:22   ` Mika Westerberg
  0 siblings, 0 replies; 39+ messages in thread
From: Mika Westerberg @ 2020-03-03 10:22 UTC (permalink / raw)
  To: Tudor.Ambarus
  Cc: bbrezillon, vigneshr, linux-mtd, miquel.raynal, richard, joel,
	andrew, Nicolas.Ferre, alexandre.belloni, Ludovic.Desroches,
	matthias.bgg, vz, michal.simek, ludovic.barre, john.garry, tglx,
	nishkadg.linux, michael, dinguyen, thor.thayer, swboyd,
	opensource, kstewart, allison, jethro, info, alexander.sverdlin,
	rfontana, linux-kernel, linux-mediatek, linux-aspeed,
	linux-arm-kernel

On Mon, Mar 02, 2020 at 06:07:51PM +0000, Tudor.Ambarus@microchip.com wrote:
> From: Boris Brezillon <bbrezillon@kernel.org>
> 
> Create a SPI NOR manufacturer driver for Intel chips, and move the
> Intel definitions outside of core.c.
> 
> Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

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

* Re: [PATCH 14/23] mtd: spi-nor: Move Macronix bits out of core.c
  2020-03-02 18:07 ` [PATCH 14/23] mtd: spi-nor: Move Macronix " Tudor.Ambarus
@ 2020-03-04  7:20   ` chenxiang (M)
  0 siblings, 0 replies; 39+ messages in thread
From: chenxiang (M) @ 2020-03-04  7:20 UTC (permalink / raw)
  To: Tudor.Ambarus, bbrezillon, vigneshr, linux-mtd
  Cc: kstewart, alexandre.belloni, linux-aspeed, thor.thayer, jethro,
	rfontana, miquel.raynal, opensource, richard, michal.simek,
	Ludovic.Desroches, joel, nishkadg.linux, john.garry, vz,
	alexander.sverdlin, matthias.bgg, tglx, swboyd, mika.westerberg,
	allison, linux-arm-kernel, andrew, Nicolas.Ferre, linux-kernel,
	dinguyen, michael, ludovic.barre, linux-mediatek, info

Hi,

在 2020/3/3 2:07, Tudor.Ambarus@microchip.com 写道:
> From: Boris Brezillon <bbrezillon@kernel.org>
>
> Create a SPI NOR manufacturer driver for Macronix chips, and move the
> Macronix definitions outside of core.c.

I have tested it with erase-wite-read-compare(1MB file) testcase on 
mx25u12835f flash, it is ok. So add:
Tested-by: Xiang Chen <chenxiang66@hisilicon.com>

>
> Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
>   drivers/mtd/spi-nor/Makefile   |  1 +
>   drivers/mtd/spi-nor/core.c     | 69 +-----------------------
>   drivers/mtd/spi-nor/core.h     |  1 +
>   drivers/mtd/spi-nor/macronix.c | 98 ++++++++++++++++++++++++++++++++++
>   4 files changed, 101 insertions(+), 68 deletions(-)
>   create mode 100644 drivers/mtd/spi-nor/macronix.c
>
> diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
> index 5c849f104cc4..c94798987801 100644
> --- a/drivers/mtd/spi-nor/Makefile
> +++ b/drivers/mtd/spi-nor/Makefile
> @@ -9,4 +9,5 @@ spi-nor-objs			+= fujitsu.o
>   spi-nor-objs			+= gigadevice.o
>   spi-nor-objs			+= intel.o
>   spi-nor-objs			+= issi.o
> +spi-nor-objs			+= macronix.o
>   obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index d781cb9af182..9d0e0fc5af45 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -2005,31 +2005,6 @@ int spi_nor_sr2_bit7_quad_enable(struct spi_nor *nor)
>   	return 0;
>   }
>   
> -static int
> -mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
> -			    const struct sfdp_parameter_header *bfpt_header,
> -			    const struct sfdp_bfpt *bfpt,
> -			    struct spi_nor_flash_parameter *params)
> -{
> -	/*
> -	 * MX25L25635F supports 4B opcodes but MX25L25635E does not.
> -	 * Unfortunately, Macronix has re-used the same JEDEC ID for both
> -	 * variants which prevents us from defining a new entry in the parts
> -	 * table.
> -	 * We need a way to differentiate MX25L25635E and MX25L25635F, and it
> -	 * seems that the F version advertises support for Fast Read 4-4-4 in
> -	 * its BFPT table.
> -	 */
> -	if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
> -		nor->flags |= SNOR_F_4B_OPCODES;
> -
> -	return 0;
> -}
> -
> -static struct spi_nor_fixups mx25l25635_fixups = {
> -	.post_bfpt = mx25l25635_post_bfpt_fixups,
> -};
> -
>   /* NOTE: double check command sets and memory organization when you add
>    * more nor chips.  This current list focusses on newer chips, which
>    * have been converging on command sets which including JEDEC ID.
> @@ -2042,39 +2017,6 @@ static struct spi_nor_fixups mx25l25635_fixups = {
>    * old entries may be missing 4K flag.
>    */
>   static const struct flash_info spi_nor_ids[] = {
> -	/* Macronix */
> -	{ "mx25l512e",   INFO(0xc22010, 0, 64 * 1024,   1, SECT_4K) },
> -	{ "mx25l2005a",  INFO(0xc22012, 0, 64 * 1024,   4, SECT_4K) },
> -	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
> -	{ "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, 0) },
> -	{ "mx25l1606e",  INFO(0xc22015, 0, 64 * 1024,  32, SECT_4K) },
> -	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, SECT_4K) },
> -	{ "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
> -	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
> -	{ "mx25u2033e",  INFO(0xc22532, 0, 64 * 1024,   4, SECT_4K) },
> -	{ "mx25u3235f",	 INFO(0xc22536, 0, 64 * 1024,  64,
> -			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> -	{ "mx25u4035",   INFO(0xc22533, 0, 64 * 1024,   8, SECT_4K) },
> -	{ "mx25u8035",   INFO(0xc22534, 0, 64 * 1024,  16, SECT_4K) },
> -	{ "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
> -	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
> -	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
> -	{ "mx25r3235f",  INFO(0xc22816, 0, 64 * 1024,  64,
> -			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> -	{ "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
> -			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> -	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
> -			 SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> -			 .fixups = &mx25l25635_fixups },
> -	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
> -	{ "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
> -			 SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> -	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
> -	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> -	{ "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> -	{ "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
> -	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
> -
>   	/* Micron <--> ST Micro */
>   	{ "n25q016a",	 INFO(0x20bb15, 0, 64 * 1024,   32, SECT_4K | SPI_NOR_QUAD_READ) },
>   	{ "n25q032",	 INFO(0x20ba16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
> @@ -2311,6 +2253,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
>   	&spi_nor_gigadevice,
>   	&spi_nor_intel,
>   	&spi_nor_issi,
> +	&spi_nor_macronix,
>   };
>   
>   static const struct flash_info *
> @@ -3090,12 +3033,6 @@ static int spi_nor_setup(struct spi_nor *nor,
>   	return nor->params.setup(nor, hwcaps);
>   }
>   
> -static void macronix_set_default_init(struct spi_nor *nor)
> -{
> -	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> -	nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
> -}
> -
>   static void sst_set_default_init(struct spi_nor *nor)
>   {
>   	nor->flags |= SNOR_F_HAS_LOCK;
> @@ -3123,10 +3060,6 @@ static void spi_nor_manufacturer_init_params(struct spi_nor *nor)
>   {
>   	/* Init flash parameters based on MFR */
>   	switch (JEDEC_MFR(nor->info)) {
> -	case SNOR_MFR_MACRONIX:
> -		macronix_set_default_init(nor);
> -		break;
> -
>   	case SNOR_MFR_ST:
>   	case SNOR_MFR_MICRON:
>   		st_micron_set_default_init(nor);
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index b4ed9acbef63..9af3a701de95 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -175,6 +175,7 @@ extern const struct spi_nor_manufacturer spi_nor_fujitsu;
>   extern const struct spi_nor_manufacturer spi_nor_gigadevice;
>   extern const struct spi_nor_manufacturer spi_nor_intel;
>   extern const struct spi_nor_manufacturer spi_nor_issi;
> +extern const struct spi_nor_manufacturer spi_nor_macronix;
>   
>   int spi_nor_write_enable(struct spi_nor *nor);
>   int spi_nor_write_disable(struct spi_nor *nor);
> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
> new file mode 100644
> index 000000000000..1ae609c44676
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/macronix.c
> @@ -0,0 +1,98 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2005, Intec Automation Inc.
> + * Copyright (C) 2014, Freescale Semiconductor, Inc.
> + */
> +
> +#include <linux/mtd/spi-nor.h>
> +
> +#include "core.h"
> +
> +static int
> +mx25l25635_post_bfpt_fixups(struct spi_nor *nor,
> +			    const struct sfdp_parameter_header *bfpt_header,
> +			    const struct sfdp_bfpt *bfpt,
> +			    struct spi_nor_flash_parameter *params)
> +{
> +	/*
> +	 * MX25L25635F supports 4B opcodes but MX25L25635E does not.
> +	 * Unfortunately, Macronix has re-used the same JEDEC ID for both
> +	 * variants which prevents us from defining a new entry in the parts
> +	 * table.
> +	 * We need a way to differentiate MX25L25635E and MX25L25635F, and it
> +	 * seems that the F version advertises support for Fast Read 4-4-4 in
> +	 * its BFPT table.
> +	 */
> +	if (bfpt->dwords[BFPT_DWORD(5)] & BFPT_DWORD5_FAST_READ_4_4_4)
> +		nor->flags |= SNOR_F_4B_OPCODES;
> +
> +	return 0;
> +}
> +
> +static struct spi_nor_fixups mx25l25635_fixups = {
> +	.post_bfpt = mx25l25635_post_bfpt_fixups,
> +};
> +
> +static const struct flash_info macronix_parts[] = {
> +	/* Macronix */
> +	{ "mx25l512e",   INFO(0xc22010, 0, 64 * 1024,   1, SECT_4K) },
> +	{ "mx25l2005a",  INFO(0xc22012, 0, 64 * 1024,   4, SECT_4K) },
> +	{ "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
> +	{ "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, 0) },
> +	{ "mx25l1606e",  INFO(0xc22015, 0, 64 * 1024,  32, SECT_4K) },
> +	{ "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, SECT_4K) },
> +	{ "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
> +	{ "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
> +	{ "mx25u2033e",  INFO(0xc22532, 0, 64 * 1024,   4, SECT_4K) },
> +	{ "mx25u3235f",	 INFO(0xc22536, 0, 64 * 1024,  64,
> +			      SECT_4K | SPI_NOR_DUAL_READ |
> +			      SPI_NOR_QUAD_READ) },
> +	{ "mx25u4035",   INFO(0xc22533, 0, 64 * 1024,   8, SECT_4K) },
> +	{ "mx25u8035",   INFO(0xc22534, 0, 64 * 1024,  16, SECT_4K) },
> +	{ "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
> +	{ "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
> +	{ "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
> +	{ "mx25r3235f",  INFO(0xc22816, 0, 64 * 1024,  64,
> +			      SECT_4K | SPI_NOR_DUAL_READ |
> +			      SPI_NOR_QUAD_READ) },
> +	{ "mx25u12835f", INFO(0xc22538, 0, 64 * 1024, 256,
> +			      SECT_4K | SPI_NOR_DUAL_READ |
> +			      SPI_NOR_QUAD_READ) },
> +	{ "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512,
> +			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ)
> +		.fixups = &mx25l25635_fixups },
> +	{ "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512,
> +			      SECT_4K | SPI_NOR_4B_OPCODES) },
> +	{ "mx25v8035f",  INFO(0xc22314, 0, 64 * 1024,  16,
> +			      SECT_4K | SPI_NOR_DUAL_READ |
> +			      SPI_NOR_QUAD_READ) },
> +	{ "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
> +	{ "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024,
> +			      SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
> +			      SPI_NOR_4B_OPCODES) },
> +	{ "mx66u51235f", INFO(0xc2253a, 0, 64 * 1024, 1024,
> +			      SECT_4K | SPI_NOR_DUAL_READ |
> +			      SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) },
> +	{ "mx66l1g45g",  INFO(0xc2201b, 0, 64 * 1024, 2048,
> +			      SECT_4K | SPI_NOR_DUAL_READ |
> +			      SPI_NOR_QUAD_READ) },
> +	{ "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048,
> +			      SPI_NOR_QUAD_READ) },
> +};
> +
> +static void macronix_default_init(struct spi_nor *nor)
> +{
> +	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> +	nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
> +}
> +
> +static const struct spi_nor_fixups macronix_fixups = {
> +	.default_init = macronix_default_init,
> +};
> +
> +const struct spi_nor_manufacturer spi_nor_macronix = {
> +	.name = "macronix",
> +	.parts = macronix_parts,
> +	.nparts = ARRAY_SIZE(macronix_parts),
> +	.fixups = &macronix_fixups,
> +};



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

* Re: [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h
  2020-03-02 18:07 ` [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h Tudor.Ambarus
@ 2020-03-07 14:49   ` Boris Brezillon
  2020-03-13  8:13   ` Vignesh Raghavendra
  1 sibling, 0 replies; 39+ messages in thread
From: Boris Brezillon @ 2020-03-07 14:49 UTC (permalink / raw)
  To: Tudor.Ambarus
  Cc: bbrezillon, vigneshr, linux-mtd, kstewart, alexandre.belloni,
	linux-aspeed, thor.thayer, jethro, rfontana, miquel.raynal,
	opensource, richard, michal.simek, Ludovic.Desroches, joel,
	nishkadg.linux, john.garry, vz, alexander.sverdlin, matthias.bgg,
	tglx, swboyd, mika.westerberg, allison, linux-arm-kernel, andrew,
	Nicolas.Ferre, linux-kernel, dinguyen, michael, ludovic.barre,
	linux-mediatek, info

On Mon, 2 Mar 2020 18:07:57 +0000
<Tudor.Ambarus@microchip.com> wrote:

> From: Tudor Ambarus <tudor.ambarus@microchip.com>
> 
> The SPI NOR controllers drivers must not be able to use structures that
> are meant just for the SPI NOR core.
> 
> struct spi_nor_flash_parameter is filled at run-time with info gathered
> from flash_info, manufacturer and sfdp data. struct spi_nor_flash_parameter
> should be opaque to the SPI NOR controller drivers, make sure it is.
> 
> spi_nor_option_flags, spi_nor_read_command, spi_nor_pp_command,
> spi_nor_read_command_index and spi_nor_pp_command_index are defined for the
> core use, make sure they are opaque to the SPI NOR controller drivers.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

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

> ---
>  drivers/mtd/spi-nor/core.c       |  86 ++++++----
>  drivers/mtd/spi-nor/core.h       | 214 +++++++++++++++++++++++++
>  drivers/mtd/spi-nor/gigadevice.c |   2 +-
>  drivers/mtd/spi-nor/issi.c       |   2 +-
>  drivers/mtd/spi-nor/macronix.c   |   4 +-
>  drivers/mtd/spi-nor/micron-st.c  |   4 +-
>  drivers/mtd/spi-nor/sfdp.c       |  10 ++
>  drivers/mtd/spi-nor/spansion.c   |   2 +-
>  drivers/mtd/spi-nor/winbond.c    |   2 +-
>  drivers/mtd/spi-nor/xilinx.c     |   4 +-
>  include/linux/mtd/spi-nor.h      | 259 +------------------------------
>  11 files changed, 294 insertions(+), 295 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index a2e1917b608d..860dac1dff90 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -802,7 +802,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
>  		ret = spi_nor_read_cr(nor, &sr_cr[1]);
>  		if (ret)
>  			return ret;
> -	} else if (nor->params.quad_enable) {
> +	} else if (nor->params->quad_enable) {
>  		/*
>  		 * If the Status Register 2 Read command (35h) is not
>  		 * supported, we should at least be sure we don't
> @@ -810,7 +810,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
>  		 *
>  		 * We can safely assume that when the Quad Enable method is
>  		 * set, the value of the QE bit is one, as a consequence of the
> -		 * nor->params.quad_enable() call.
> +		 * nor->params->quad_enable() call.
>  		 *
>  		 * We can safely assume that the Quad Enable bit is present in
>  		 * the Status Register 2 at BIT(1). According to the JESD216
> @@ -1075,6 +1075,11 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
>  				      ARRAY_SIZE(spi_nor_3to4_erase));
>  }
>  
> +static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
> +{
> +	return !!nor->params->erase_map.uniform_erase_type;
> +}
> +
>  static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
>  {
>  	nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
> @@ -1082,7 +1087,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
>  	nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
>  
>  	if (!spi_nor_has_uniform_erase(nor)) {
> -		struct spi_nor_erase_map *map = &nor->params.erase_map;
> +		struct spi_nor_erase_map *map = &nor->params->erase_map;
>  		struct spi_nor_erase_type *erase;
>  		int i;
>  
> @@ -1119,10 +1124,10 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor)
>  
>  static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr)
>  {
> -	if (!nor->params.convert_addr)
> +	if (!nor->params->convert_addr)
>  		return addr;
>  
> -	return nor->params.convert_addr(nor, addr);
> +	return nor->params->convert_addr(nor, addr);
>  }
>  
>  /*
> @@ -1227,6 +1232,16 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
>  	return NULL;
>  }
>  
> +static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region)
> +{
> +	return region->offset & SNOR_LAST_REGION;
> +}
> +
> +static u64 spi_nor_region_end(const struct spi_nor_erase_region *region)
> +{
> +	return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
> +}
> +
>  /**
>   * spi_nor_region_next() - get the next spi nor region
>   * @region:	pointer to a structure that describes a SPI NOR erase region
> @@ -1331,7 +1346,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
>  				       struct list_head *erase_list,
>  				       u64 addr, u32 len)
>  {
> -	const struct spi_nor_erase_map *map = &nor->params.erase_map;
> +	const struct spi_nor_erase_map *map = &nor->params->erase_map;
>  	const struct spi_nor_erase_type *erase, *prev_erase = NULL;
>  	struct spi_nor_erase_region *region;
>  	struct spi_nor_erase_command *cmd = NULL;
> @@ -1817,7 +1832,7 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  	if (ret)
>  		return ret;
>  
> -	ret = nor->params.locking_ops->lock(nor, ofs, len);
> +	ret = nor->params->locking_ops->lock(nor, ofs, len);
>  
>  	spi_nor_unlock_and_unprep(nor);
>  	return ret;
> @@ -1832,7 +1847,7 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  	if (ret)
>  		return ret;
>  
> -	ret = nor->params.locking_ops->unlock(nor, ofs, len);
> +	ret = nor->params->locking_ops->unlock(nor, ofs, len);
>  
>  	spi_nor_unlock_and_unprep(nor);
>  	return ret;
> @@ -1847,7 +1862,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  	if (ret)
>  		return ret;
>  
> -	ret = nor->params.locking_ops->is_locked(nor, ofs, len);
> +	ret = nor->params->locking_ops->is_locked(nor, ofs, len);
>  
>  	spi_nor_unlock_and_unprep(nor);
>  	return ret;
> @@ -2312,7 +2327,7 @@ static int spi_nor_spimem_check_pp(struct spi_nor *nor,
>  static void
>  spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
>  {
> -	struct spi_nor_flash_parameter *params =  &nor->params;
> +	struct spi_nor_flash_parameter *params = nor->params;
>  	unsigned int cap;
>  
>  	/* DTR modes are not supported yet, mask them all. */
> @@ -2411,7 +2426,7 @@ static int spi_nor_select_read(struct spi_nor *nor,
>  	if (cmd < 0)
>  		return -EINVAL;
>  
> -	read = &nor->params.reads[cmd];
> +	read = &nor->params->reads[cmd];
>  	nor->read_opcode = read->opcode;
>  	nor->read_proto = read->proto;
>  
> @@ -2442,7 +2457,7 @@ static int spi_nor_select_pp(struct spi_nor *nor,
>  	if (cmd < 0)
>  		return -EINVAL;
>  
> -	pp = &nor->params.page_programs[cmd];
> +	pp = &nor->params->page_programs[cmd];
>  	nor->program_opcode = pp->opcode;
>  	nor->write_proto = pp->proto;
>  	return 0;
> @@ -2503,7 +2518,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
>  
>  static int spi_nor_select_erase(struct spi_nor *nor)
>  {
> -	struct spi_nor_erase_map *map = &nor->params.erase_map;
> +	struct spi_nor_erase_map *map = &nor->params->erase_map;
>  	const struct spi_nor_erase_type *erase = NULL;
>  	struct mtd_info *mtd = &nor->mtd;
>  	u32 wanted_size = nor->info->sector_size;
> @@ -2552,7 +2567,7 @@ static int spi_nor_select_erase(struct spi_nor *nor)
>  static int spi_nor_default_setup(struct spi_nor *nor,
>  				 const struct spi_nor_hwcaps *hwcaps)
>  {
> -	struct spi_nor_flash_parameter *params = &nor->params;
> +	struct spi_nor_flash_parameter *params = nor->params;
>  	u32 ignored_mask, shared_mask;
>  	int err;
>  
> @@ -2613,10 +2628,10 @@ static int spi_nor_default_setup(struct spi_nor *nor,
>  static int spi_nor_setup(struct spi_nor *nor,
>  			 const struct spi_nor_hwcaps *hwcaps)
>  {
> -	if (!nor->params.setup)
> +	if (!nor->params->setup)
>  		return 0;
>  
> -	return nor->params.setup(nor, hwcaps);
> +	return nor->params->setup(nor, hwcaps);
>  }
>  
>  /**
> @@ -2646,13 +2661,13 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
>  {
>  	struct spi_nor_flash_parameter sfdp_params;
>  
> -	memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params));
> +	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
>  
>  	if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
>  		nor->addr_width = 0;
>  		nor->flags &= ~SNOR_F_4B_OPCODES;
>  	} else {
> -		memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
> +		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
>  	}
>  }
>  
> @@ -2663,7 +2678,7 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
>   */
>  static void spi_nor_info_init_params(struct spi_nor *nor)
>  {
> -	struct spi_nor_flash_parameter *params = &nor->params;
> +	struct spi_nor_flash_parameter *params = nor->params;
>  	struct spi_nor_erase_map *map = &params->erase_map;
>  	const struct flash_info *info = nor->info;
>  	struct device_node *np = spi_nor_get_flash_node(nor);
> @@ -2782,8 +2797,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
>  	 * NOR protection support. When locking_ops are not provided, we pick
>  	 * the default ones.
>  	 */
> -	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops)
> -		nor->params.locking_ops = &spi_nor_sr_locking_ops;
> +	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
> +		nor->params->locking_ops = &spi_nor_sr_locking_ops;
>  }
>  
>  /**
> @@ -2823,8 +2838,12 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
>   * ->default_init() hook or the SFDP parser do not set specific params.
>   *		spi_nor_late_init_params()
>   */
> -static void spi_nor_init_params(struct spi_nor *nor)
> +static int spi_nor_init_params(struct spi_nor *nor)
>  {
> +	nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
> +	if (!nor->params)
> +		return -ENOMEM;
> +
>  	spi_nor_info_init_params(nor);
>  
>  	spi_nor_manufacturer_init_params(nor);
> @@ -2836,6 +2855,8 @@ static void spi_nor_init_params(struct spi_nor *nor)
>  	spi_nor_post_sfdp_fixups(nor);
>  
>  	spi_nor_late_init_params(nor);
> +
> +	return 0;
>  }
>  
>  /**
> @@ -2846,14 +2867,14 @@ static void spi_nor_init_params(struct spi_nor *nor)
>   */
>  static int spi_nor_quad_enable(struct spi_nor *nor)
>  {
> -	if (!nor->params.quad_enable)
> +	if (!nor->params->quad_enable)
>  		return 0;
>  
>  	if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
>  	      spi_nor_get_protocol_width(nor->write_proto) == 4))
>  		return 0;
>  
> -	return nor->params.quad_enable(nor);
> +	return nor->params->quad_enable(nor);
>  }
>  
>  /**
> @@ -2868,7 +2889,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor)
>  static int spi_nor_unlock_all(struct spi_nor *nor)
>  {
>  	if (nor->flags & SNOR_F_HAS_LOCK)
> -		return spi_nor_unlock(&nor->mtd, 0, nor->params.size);
> +		return spi_nor_unlock(&nor->mtd, 0, nor->params->size);
>  
>  	return 0;
>  }
> @@ -2899,7 +2920,7 @@ static int spi_nor_init(struct spi_nor *nor)
>  		 */
>  		WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
>  			  "enabling reset hack; may not recover from unexpected reboots\n");
> -		nor->params.set_4byte(nor, true);
> +		nor->params->set_4byte(nor, true);
>  	}
>  
>  	return 0;
> @@ -2923,7 +2944,7 @@ void spi_nor_restore(struct spi_nor *nor)
>  	/* restore the addressing mode */
>  	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
>  	    nor->flags & SNOR_F_BROKEN_RESET)
> -		nor->params.set_4byte(nor, false);
> +		nor->params->set_4byte(nor, false);
>  }
>  EXPORT_SYMBOL_GPL(spi_nor_restore);
>  
> @@ -3028,7 +3049,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>  	struct device *dev = nor->dev;
>  	struct mtd_info *mtd = &nor->mtd;
>  	struct device_node *np = spi_nor_get_flash_node(nor);
> -	struct spi_nor_flash_parameter *params = &nor->params;
>  	int ret;
>  	int i;
>  
> @@ -3079,7 +3099,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>  	mtd->_write = spi_nor_write;
>  
>  	/* Init flash parameters based on flash_info struct and SFDP */
> -	spi_nor_init_params(nor);
> +	ret = spi_nor_init_params(nor);
> +	if (ret)
> +		return ret;
>  
>  	if (!mtd->name)
>  		mtd->name = dev_name(dev);
> @@ -3087,12 +3109,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>  	mtd->type = MTD_NORFLASH;
>  	mtd->writesize = 1;
>  	mtd->flags = MTD_CAP_NORFLASH;
> -	mtd->size = params->size;
> +	mtd->size = nor->params->size;
>  	mtd->_erase = spi_nor_erase;
>  	mtd->_read = spi_nor_read;
>  	mtd->_resume = spi_nor_resume;
>  
> -	if (nor->params.locking_ops) {
> +	if (nor->params->locking_ops) {
>  		mtd->_lock = spi_nor_lock;
>  		mtd->_unlock = spi_nor_unlock;
>  		mtd->_is_locked = spi_nor_is_locked;
> @@ -3115,7 +3137,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>  		mtd->flags |= MTD_NO_ERASE;
>  
>  	mtd->dev.parent = dev;
> -	nor->page_size = params->page_size;
> +	nor->page_size = nor->params->page_size;
>  	mtd->writebufsize = nor->page_size;
>  
>  	if (of_property_read_bool(np, "broken-flash-reset"))
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 3541a84c03d8..7654b6f3b966 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -11,6 +11,220 @@
>  
>  #define SPI_NOR_MAX_ID_LEN	6
>  
> +enum spi_nor_option_flags {
> +	SNOR_F_USE_FSR		= BIT(0),
> +	SNOR_F_HAS_SR_TB	= BIT(1),
> +	SNOR_F_NO_OP_CHIP_ERASE	= BIT(2),
> +	SNOR_F_READY_XSR_RDY	= BIT(3),
> +	SNOR_F_USE_CLSR		= BIT(4),
> +	SNOR_F_BROKEN_RESET	= BIT(5),
> +	SNOR_F_4B_OPCODES	= BIT(6),
> +	SNOR_F_HAS_4BAIT	= BIT(7),
> +	SNOR_F_HAS_LOCK		= BIT(8),
> +	SNOR_F_HAS_16BIT_SR	= BIT(9),
> +	SNOR_F_NO_READ_CR	= BIT(10),
> +	SNOR_F_HAS_SR_TB_BIT6	= BIT(11),
> +};
> +
> +struct spi_nor_read_command {
> +	u8			num_mode_clocks;
> +	u8			num_wait_states;
> +	u8			opcode;
> +	enum spi_nor_protocol	proto;
> +};
> +
> +struct spi_nor_pp_command {
> +	u8			opcode;
> +	enum spi_nor_protocol	proto;
> +};
> +
> +enum spi_nor_read_command_index {
> +	SNOR_CMD_READ,
> +	SNOR_CMD_READ_FAST,
> +	SNOR_CMD_READ_1_1_1_DTR,
> +
> +	/* Dual SPI */
> +	SNOR_CMD_READ_1_1_2,
> +	SNOR_CMD_READ_1_2_2,
> +	SNOR_CMD_READ_2_2_2,
> +	SNOR_CMD_READ_1_2_2_DTR,
> +
> +	/* Quad SPI */
> +	SNOR_CMD_READ_1_1_4,
> +	SNOR_CMD_READ_1_4_4,
> +	SNOR_CMD_READ_4_4_4,
> +	SNOR_CMD_READ_1_4_4_DTR,
> +
> +	/* Octal SPI */
> +	SNOR_CMD_READ_1_1_8,
> +	SNOR_CMD_READ_1_8_8,
> +	SNOR_CMD_READ_8_8_8,
> +	SNOR_CMD_READ_1_8_8_DTR,
> +
> +	SNOR_CMD_READ_MAX
> +};
> +
> +enum spi_nor_pp_command_index {
> +	SNOR_CMD_PP,
> +
> +	/* Quad SPI */
> +	SNOR_CMD_PP_1_1_4,
> +	SNOR_CMD_PP_1_4_4,
> +	SNOR_CMD_PP_4_4_4,
> +
> +	/* Octal SPI */
> +	SNOR_CMD_PP_1_1_8,
> +	SNOR_CMD_PP_1_8_8,
> +	SNOR_CMD_PP_8_8_8,
> +
> +	SNOR_CMD_PP_MAX
> +};
> +
> +/**
> + * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
> + * @size:		the size of the sector/block erased by the erase type.
> + *			JEDEC JESD216B imposes erase sizes to be a power of 2.
> + * @size_shift:		@size is a power of 2, the shift is stored in
> + *			@size_shift.
> + * @size_mask:		the size mask based on @size_shift.
> + * @opcode:		the SPI command op code to erase the sector/block.
> + * @idx:		Erase Type index as sorted in the Basic Flash Parameter
> + *			Table. It will be used to synchronize the supported
> + *			Erase Types with the ones identified in the SFDP
> + *			optional tables.
> + */
> +struct spi_nor_erase_type {
> +	u32	size;
> +	u32	size_shift;
> +	u32	size_mask;
> +	u8	opcode;
> +	u8	idx;
> +};
> +
> +/**
> + * struct spi_nor_erase_command - Used for non-uniform erases
> + * The structure is used to describe a list of erase commands to be executed
> + * once we validate that the erase can be performed. The elements in the list
> + * are run-length encoded.
> + * @list:		for inclusion into the list of erase commands.
> + * @count:		how many times the same erase command should be
> + *			consecutively used.
> + * @size:		the size of the sector/block erased by the command.
> + * @opcode:		the SPI command op code to erase the sector/block.
> + */
> +struct spi_nor_erase_command {
> +	struct list_head	list;
> +	u32			count;
> +	u32			size;
> +	u8			opcode;
> +};
> +
> +/**
> + * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
> + * @offset:		the offset in the data array of erase region start.
> + *			LSB bits are used as a bitmask encoding flags to
> + *			determine if this region is overlaid, if this region is
> + *			the last in the SPI NOR flash memory and to indicate
> + *			all the supported erase commands inside this region.
> + *			The erase types are sorted in ascending order with the
> + *			smallest Erase Type size being at BIT(0).
> + * @size:		the size of the region in bytes.
> + */
> +struct spi_nor_erase_region {
> +	u64		offset;
> +	u64		size;
> +};
> +
> +#define SNOR_ERASE_TYPE_MAX	4
> +#define SNOR_ERASE_TYPE_MASK	GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
> +
> +#define SNOR_LAST_REGION	BIT(4)
> +#define SNOR_OVERLAID_REGION	BIT(5)
> +
> +#define SNOR_ERASE_FLAGS_MAX	6
> +#define SNOR_ERASE_FLAGS_MASK	GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
> +
> +/**
> + * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
> + * @regions:		array of erase regions. The regions are consecutive in
> + *			address space. Walking through the regions is done
> + *			incrementally.
> + * @uniform_region:	a pre-allocated erase region for SPI NOR with a uniform
> + *			sector size (legacy implementation).
> + * @erase_type:		an array of erase types shared by all the regions.
> + *			The erase types are sorted in ascending order, with the
> + *			smallest Erase Type size being the first member in the
> + *			erase_type array.
> + * @uniform_erase_type:	bitmask encoding erase types that can erase the
> + *			entire memory. This member is completed at init by
> + *			uniform and non-uniform SPI NOR flash memories if they
> + *			support at least one erase type that can erase the
> + *			entire memory.
> + */
> +struct spi_nor_erase_map {
> +	struct spi_nor_erase_region	*regions;
> +	struct spi_nor_erase_region	uniform_region;
> +	struct spi_nor_erase_type	erase_type[SNOR_ERASE_TYPE_MAX];
> +	u8				uniform_erase_type;
> +};
> +
> +/**
> + * struct spi_nor_locking_ops - SPI NOR locking methods
> + * @lock:	lock a region of the SPI NOR.
> + * @unlock:	unlock a region of the SPI NOR.
> + * @is_locked:	check if a region of the SPI NOR is completely locked
> + */
> +struct spi_nor_locking_ops {
> +	int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> +	int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> +	int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> +};
> +
> +/**
> + * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
> + * Includes legacy flash parameters and settings that can be overwritten
> + * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
> + * Serial Flash Discoverable Parameters (SFDP) tables.
> + *
> + * @size:		the flash memory density in bytes.
> + * @page_size:		the page size of the SPI NOR flash memory.
> + * @hwcaps:		describes the read and page program hardware
> + *			capabilities.
> + * @reads:		read capabilities ordered by priority: the higher index
> + *                      in the array, the higher priority.
> + * @page_programs:	page program capabilities ordered by priority: the
> + *                      higher index in the array, the higher priority.
> + * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
> + *                      Table.
> + * @quad_enable:	enables SPI NOR quad mode.
> + * @set_4byte:		puts the SPI NOR in 4 byte addressing mode.
> + * @convert_addr:	converts an absolute address into something the flash
> + *                      will understand. Particularly useful when pagesize is
> + *                      not a power-of-2.
> + * @setup:              configures the SPI NOR memory. Useful for SPI NOR
> + *                      flashes that have peculiarities to the SPI NOR standard
> + *                      e.g. different opcodes, specific address calculation,
> + *                      page size, etc.
> + * @locking_ops:	SPI NOR locking methods.
> + */
> +struct spi_nor_flash_parameter {
> +	u64				size;
> +	u32				page_size;
> +
> +	struct spi_nor_hwcaps		hwcaps;
> +	struct spi_nor_read_command	reads[SNOR_CMD_READ_MAX];
> +	struct spi_nor_pp_command	page_programs[SNOR_CMD_PP_MAX];
> +
> +	struct spi_nor_erase_map        erase_map;
> +
> +	int (*quad_enable)(struct spi_nor *nor);
> +	int (*set_4byte)(struct spi_nor *nor, bool enable);
> +	u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
> +	int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
> +
> +	const struct spi_nor_locking_ops *locking_ops;
> +};
> +
>  /**
>   * struct spi_nor_fixups - SPI NOR fixup hooks
>   * @default_init: called after default flash parameters init. Used to tweak
> diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
> index 7930e4490dab..447d84bb2128 100644
> --- a/drivers/mtd/spi-nor/gigadevice.c
> +++ b/drivers/mtd/spi-nor/gigadevice.c
> @@ -16,7 +16,7 @@ static void gd25q256_default_init(struct spi_nor *nor)
>  	 * indicate the quad_enable method for this case, we need
>  	 * to set it in the default_init fixup hook.
>  	 */
> -	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> +	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
>  }
>  
>  static struct spi_nor_fixups gd25q256_fixups = {
> diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
> index 3a1c34c41388..ffcb60e54a80 100644
> --- a/drivers/mtd/spi-nor/issi.c
> +++ b/drivers/mtd/spi-nor/issi.c
> @@ -68,7 +68,7 @@ static const struct flash_info issi_parts[] = {
>  
>  static void issi_default_init(struct spi_nor *nor)
>  {
> -	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> +	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
>  }
>  
>  static const struct spi_nor_fixups issi_fixups = {
> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
> index 1ae609c44676..d73bd0363144 100644
> --- a/drivers/mtd/spi-nor/macronix.c
> +++ b/drivers/mtd/spi-nor/macronix.c
> @@ -82,8 +82,8 @@ static const struct flash_info macronix_parts[] = {
>  
>  static void macronix_default_init(struct spi_nor *nor)
>  {
> -	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> -	nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
> +	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
> +	nor->params->set_4byte = spi_nor_en4_ex4_set_4byte;
>  }
>  
>  static const struct spi_nor_fixups macronix_fixups = {
> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
> index 8017ca58b3a5..5be817d2f27c 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -106,8 +106,8 @@ static void micron_st_default_init(struct spi_nor *nor)
>  {
>  	nor->flags |= SNOR_F_HAS_LOCK;
>  	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
> -	nor->params.quad_enable = NULL;
> -	nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
> +	nor->params->quad_enable = NULL;
> +	nor->params->set_4byte = spi_nor_en4_ex4_wen_set_4byte;
>  }
>  
>  static const struct spi_nor_fixups micron_st_fixups = {
> diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
> index b790c3ec871f..6829dc7e4f74 100644
> --- a/drivers/mtd/spi-nor/sfdp.c
> +++ b/drivers/mtd/spi-nor/sfdp.c
> @@ -734,6 +734,16 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
>  	return ret;
>  }
>  
> +static void spi_nor_region_mark_end(struct spi_nor_erase_region *region)
> +{
> +	region->offset |= SNOR_LAST_REGION;
> +}
> +
> +static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
> +{
> +	region->offset |= SNOR_OVERLAID_REGION;
> +}
> +
>  /**
>   * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid
>   * @region:	pointer to a structure that describes a SPI NOR erase region
> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
> index 16683983a20e..6756202ace4b 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -74,7 +74,7 @@ static const struct flash_info spansion_parts[] = {
>  
>  static void spansion_post_sfdp_fixups(struct spi_nor *nor)
>  {
> -	if (nor->params.size <= SZ_16M)
> +	if (nor->params->size <= SZ_16M)
>  		return;
>  
>  	nor->flags |= SNOR_F_4B_OPCODES;
> diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
> index 1e77dffbf729..f15be50024d1 100644
> --- a/drivers/mtd/spi-nor/winbond.c
> +++ b/drivers/mtd/spi-nor/winbond.c
> @@ -97,7 +97,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable)
>  
>  static void winbond_default_init(struct spi_nor *nor)
>  {
> -	nor->params.set_4byte = winbond_set_4byte;
> +	nor->params->set_4byte = winbond_set_4byte;
>  }
>  
>  static const struct spi_nor_fixups winbond_fixups = {
> diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
> index fcf635d89f65..1138bdbf4199 100644
> --- a/drivers/mtd/spi-nor/xilinx.c
> +++ b/drivers/mtd/spi-nor/xilinx.c
> @@ -70,7 +70,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
>  		nor->mtd.erasesize = 8 * nor->page_size;
>  	} else {
>  		/* Flash in Default addressing mode */
> -		nor->params.convert_addr = s3an_convert_addr;
> +		nor->params->convert_addr = s3an_convert_addr;
>  		nor->mtd.erasesize = nor->info->sector_size;
>  	}
>  
> @@ -79,7 +79,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
>  
>  static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
>  {
> -	nor->params.setup = xilinx_nor_setup;
> +	nor->params->setup = xilinx_nor_setup;
>  }
>  
>  static const struct spi_nor_fixups xilinx_fixups = {
> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
> index dde2988a809e..d3d34c4eea48 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -227,110 +227,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto)
>  	return spi_nor_get_protocol_data_nbits(proto);
>  }
>  
> -enum spi_nor_option_flags {
> -	SNOR_F_USE_FSR		= BIT(0),
> -	SNOR_F_HAS_SR_TB	= BIT(1),
> -	SNOR_F_NO_OP_CHIP_ERASE	= BIT(2),
> -	SNOR_F_READY_XSR_RDY	= BIT(3),
> -	SNOR_F_USE_CLSR		= BIT(4),
> -	SNOR_F_BROKEN_RESET	= BIT(5),
> -	SNOR_F_4B_OPCODES	= BIT(6),
> -	SNOR_F_HAS_4BAIT	= BIT(7),
> -	SNOR_F_HAS_LOCK		= BIT(8),
> -	SNOR_F_HAS_16BIT_SR	= BIT(9),
> -	SNOR_F_NO_READ_CR	= BIT(10),
> -	SNOR_F_HAS_SR_TB_BIT6	= BIT(11),
> -
> -};
> -
> -/**
> - * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
> - * @size:		the size of the sector/block erased by the erase type.
> - *			JEDEC JESD216B imposes erase sizes to be a power of 2.
> - * @size_shift:		@size is a power of 2, the shift is stored in
> - *			@size_shift.
> - * @size_mask:		the size mask based on @size_shift.
> - * @opcode:		the SPI command op code to erase the sector/block.
> - * @idx:		Erase Type index as sorted in the Basic Flash Parameter
> - *			Table. It will be used to synchronize the supported
> - *			Erase Types with the ones identified in the SFDP
> - *			optional tables.
> - */
> -struct spi_nor_erase_type {
> -	u32	size;
> -	u32	size_shift;
> -	u32	size_mask;
> -	u8	opcode;
> -	u8	idx;
> -};
> -
> -/**
> - * struct spi_nor_erase_command - Used for non-uniform erases
> - * The structure is used to describe a list of erase commands to be executed
> - * once we validate that the erase can be performed. The elements in the list
> - * are run-length encoded.
> - * @list:		for inclusion into the list of erase commands.
> - * @count:		how many times the same erase command should be
> - *			consecutively used.
> - * @size:		the size of the sector/block erased by the command.
> - * @opcode:		the SPI command op code to erase the sector/block.
> - */
> -struct spi_nor_erase_command {
> -	struct list_head	list;
> -	u32			count;
> -	u32			size;
> -	u8			opcode;
> -};
> -
> -/**
> - * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
> - * @offset:		the offset in the data array of erase region start.
> - *			LSB bits are used as a bitmask encoding flags to
> - *			determine if this region is overlaid, if this region is
> - *			the last in the SPI NOR flash memory and to indicate
> - *			all the supported erase commands inside this region.
> - *			The erase types are sorted in ascending order with the
> - *			smallest Erase Type size being at BIT(0).
> - * @size:		the size of the region in bytes.
> - */
> -struct spi_nor_erase_region {
> -	u64		offset;
> -	u64		size;
> -};
> -
> -#define SNOR_ERASE_TYPE_MAX	4
> -#define SNOR_ERASE_TYPE_MASK	GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
> -
> -#define SNOR_LAST_REGION	BIT(4)
> -#define SNOR_OVERLAID_REGION	BIT(5)
> -
> -#define SNOR_ERASE_FLAGS_MAX	6
> -#define SNOR_ERASE_FLAGS_MASK	GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
> -
> -/**
> - * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
> - * @regions:		array of erase regions. The regions are consecutive in
> - *			address space. Walking through the regions is done
> - *			incrementally.
> - * @uniform_region:	a pre-allocated erase region for SPI NOR with a uniform
> - *			sector size (legacy implementation).
> - * @erase_type:		an array of erase types shared by all the regions.
> - *			The erase types are sorted in ascending order, with the
> - *			smallest Erase Type size being the first member in the
> - *			erase_type array.
> - * @uniform_erase_type:	bitmask encoding erase types that can erase the
> - *			entire memory. This member is completed at init by
> - *			uniform and non-uniform SPI NOR flash memories if they
> - *			support at least one erase type that can erase the
> - *			entire memory.
> - */
> -struct spi_nor_erase_map {
> -	struct spi_nor_erase_region	*regions;
> -	struct spi_nor_erase_region	uniform_region;
> -	struct spi_nor_erase_type	erase_type[SNOR_ERASE_TYPE_MAX];
> -	u8				uniform_erase_type;
> -};
> -
>  /**
>   * struct spi_nor_hwcaps - Structure for describing the hardware capabilies
>   * supported by the SPI controller (bus master).
> @@ -406,61 +302,7 @@ struct spi_nor_hwcaps {
>  #define SNOR_HWCAPS_ALL		(SNOR_HWCAPS_READ_MASK |	\
>  				 SNOR_HWCAPS_PP_MASK)
>  
> -struct spi_nor_read_command {
> -	u8			num_mode_clocks;
> -	u8			num_wait_states;
> -	u8			opcode;
> -	enum spi_nor_protocol	proto;
> -};
> -
> -struct spi_nor_pp_command {
> -	u8			opcode;
> -	enum spi_nor_protocol	proto;
> -};
> -
> -enum spi_nor_read_command_index {
> -	SNOR_CMD_READ,
> -	SNOR_CMD_READ_FAST,
> -	SNOR_CMD_READ_1_1_1_DTR,
> -
> -	/* Dual SPI */
> -	SNOR_CMD_READ_1_1_2,
> -	SNOR_CMD_READ_1_2_2,
> -	SNOR_CMD_READ_2_2_2,
> -	SNOR_CMD_READ_1_2_2_DTR,
> -
> -	/* Quad SPI */
> -	SNOR_CMD_READ_1_1_4,
> -	SNOR_CMD_READ_1_4_4,
> -	SNOR_CMD_READ_4_4_4,
> -	SNOR_CMD_READ_1_4_4_DTR,
> -
> -	/* Octal SPI */
> -	SNOR_CMD_READ_1_1_8,
> -	SNOR_CMD_READ_1_8_8,
> -	SNOR_CMD_READ_8_8_8,
> -	SNOR_CMD_READ_1_8_8_DTR,
> -
> -	SNOR_CMD_READ_MAX
> -};
> -
> -enum spi_nor_pp_command_index {
> -	SNOR_CMD_PP,
> -
> -	/* Quad SPI */
> -	SNOR_CMD_PP_1_1_4,
> -	SNOR_CMD_PP_1_4_4,
> -	SNOR_CMD_PP_4_4_4,
> -
> -	/* Octal SPI */
> -	SNOR_CMD_PP_1_1_8,
> -	SNOR_CMD_PP_1_8_8,
> -	SNOR_CMD_PP_8_8_8,
> -
> -	SNOR_CMD_PP_MAX
> -};
> -
> -/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */
> +/* Forward declaration that is used in 'struct spi_nor_controller_ops' */
>  struct spi_nor;
>  
>  /**
> @@ -491,74 +333,14 @@ struct spi_nor_controller_ops {
>  	int (*erase)(struct spi_nor *nor, loff_t offs);
>  };
>  
> -/**
> - * struct spi_nor_locking_ops - SPI NOR locking methods
> - * @lock:	lock a region of the SPI NOR.
> - * @unlock:	unlock a region of the SPI NOR.
> - * @is_locked:	check if a region of the SPI NOR is completely locked
> - */
> -struct spi_nor_locking_ops {
> -	int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> -	int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> -	int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> -};
> -
> -/**
> - * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
> - * Includes legacy flash parameters and settings that can be overwritten
> - * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
> - * Serial Flash Discoverable Parameters (SFDP) tables.
> - *
> - * @size:		the flash memory density in bytes.
> - * @page_size:		the page size of the SPI NOR flash memory.
> - * @hwcaps:		describes the read and page program hardware
> - *			capabilities.
> - * @reads:		read capabilities ordered by priority: the higher index
> - *                      in the array, the higher priority.
> - * @page_programs:	page program capabilities ordered by priority: the
> - *                      higher index in the array, the higher priority.
> - * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
> - *                      Table.
> - * @quad_enable:	enables SPI NOR quad mode.
> - * @set_4byte:		puts the SPI NOR in 4 byte addressing mode.
> - * @convert_addr:	converts an absolute address into something the flash
> - *                      will understand. Particularly useful when pagesize is
> - *                      not a power-of-2.
> - * @setup:              configures the SPI NOR memory. Useful for SPI NOR
> - *                      flashes that have peculiarities to the SPI NOR standard
> - *                      e.g. different opcodes, specific address calculation,
> - *                      page size, etc.
> - * @locking_ops:	SPI NOR locking methods.
> - */
> -struct spi_nor_flash_parameter {
> -	u64				size;
> -	u32				page_size;
> -
> -	struct spi_nor_hwcaps		hwcaps;
> -	struct spi_nor_read_command	reads[SNOR_CMD_READ_MAX];
> -	struct spi_nor_pp_command	page_programs[SNOR_CMD_PP_MAX];
>  
> -	struct spi_nor_erase_map        erase_map;
> -
> -	int (*quad_enable)(struct spi_nor *nor);
> -	int (*set_4byte)(struct spi_nor *nor, bool enable);
> -	u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
> -	int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
> -
> -	const struct spi_nor_locking_ops *locking_ops;
> -};
> -
> -/**
> - * struct flash_info - Forward declaration of a structure used internally by
> - *		       spi_nor_scan()
> +/*
> + * Forward declarations that are used internally by the core and manufacturer
> + * drivers.
>   */
>  struct flash_info;
> -
> -/**
> - * struct spi_nor_manufacturer - Forward declaration of a structure used
> - * internally by the core and manufacturer drivers.
> - */
>  struct spi_nor_manufacturer;
> +struct spi_nor_flash_parameter;
>  
>  /**
>   * struct spi_nor - Structure for defining a the SPI NOR layer
> @@ -613,7 +395,7 @@ struct spi_nor {
>  
>  	const struct spi_nor_controller_ops *controller_ops;
>  
> -	struct spi_nor_flash_parameter params;
> +	struct spi_nor_flash_parameter *params;
>  
>  	struct {
>  		struct spi_mem_dirmap_desc *rdesc;
> @@ -623,35 +405,6 @@ struct spi_nor {
>  	void *priv;
>  };
>  
> -static u64 __maybe_unused
> -spi_nor_region_is_last(const struct spi_nor_erase_region *region)
> -{
> -	return region->offset & SNOR_LAST_REGION;
> -}
> -
> -static u64 __maybe_unused
> -spi_nor_region_end(const struct spi_nor_erase_region *region)
> -{
> -	return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
> -}
> -
> -static void __maybe_unused
> -spi_nor_region_mark_end(struct spi_nor_erase_region *region)
> -{
> -	region->offset |= SNOR_LAST_REGION;
> -}
> -
> -static void __maybe_unused
> -spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
> -{
> -	region->offset |= SNOR_OVERLAID_REGION;
> -}
> -
> -static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
> -{
> -	return !!nor->params.erase_map.uniform_erase_type;
> -}
> -
>  static inline void spi_nor_set_flash_node(struct spi_nor *nor,
>  					  struct device_node *np)
>  {


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

* Re: [PATCH 03/23] mtd: spi-nor: Move SFDP logic out of the core
  2020-03-02 18:07 ` [PATCH 03/23] mtd: spi-nor: Move SFDP logic out of the core Tudor.Ambarus
@ 2020-03-07 14:50   ` Boris Brezillon
  0 siblings, 0 replies; 39+ messages in thread
From: Boris Brezillon @ 2020-03-07 14:50 UTC (permalink / raw)
  To: Tudor.Ambarus
  Cc: bbrezillon, vigneshr, linux-mtd, kstewart, alexandre.belloni,
	linux-aspeed, thor.thayer, jethro, rfontana, miquel.raynal,
	opensource, richard, michal.simek, Ludovic.Desroches, joel,
	nishkadg.linux, john.garry, vz, alexander.sverdlin, matthias.bgg,
	tglx, swboyd, mika.westerberg, allison, linux-arm-kernel, andrew,
	Nicolas.Ferre, linux-kernel, dinguyen, michael, ludovic.barre,
	linux-mediatek, info

On Mon, 2 Mar 2020 18:07:46 +0000
<Tudor.Ambarus@microchip.com> wrote:

> From: Tudor Ambarus <tudor.ambarus@microchip.com>
> 
> It makes the core file a bit smaller and provides better separation
> between the SFDP parsing and core logic.
> 
> Keep the core.h and sfdp.h definitions private in drivers/mtd/spi-nor/.
> Both expose just the definitions that are required by the core and
> manufacturer drivers. None of the SPI NOR controller drivers should
> include them.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

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

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

* Re: [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name
  2020-03-02 18:07 ` [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name Tudor.Ambarus
@ 2020-03-13  6:04   ` Vignesh Raghavendra
  2020-03-13  9:30     ` Boris Brezillon
  0 siblings, 1 reply; 39+ messages in thread
From: Vignesh Raghavendra @ 2020-03-13  6:04 UTC (permalink / raw)
  To: Tudor.Ambarus, bbrezillon, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel



On 02/03/20 11:37 pm, Tudor.Ambarus@microchip.com wrote:
> From: Boris Brezillon <bbrezillon@kernel.org>
> 
> Replace the manufacturer prefix by something describing more precisely
> what those functions do.
> 
> Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> [tudor.ambarus@microchip.com: prepend spi_nor_ to all modified methods.]
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
>  drivers/mtd/spi-nor/spi-nor.c | 88 ++++++++++++++++++-----------------
>  1 file changed, 45 insertions(+), 43 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> index caf0c109cca0..b15e262765e1 100644
> --- a/drivers/mtd/spi-nor/spi-nor.c
> +++ b/drivers/mtd/spi-nor/spi-nor.c
> @@ -568,14 +568,15 @@ static int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
>  }
>  
>  /**
> - * macronix_set_4byte() - Set 4-byte address mode for Macronix flashes.
> + * spi_nor_en4_ex4_set_4byte() - Enter/Exit 4-byte mode for Macronix like
> + * flashes.
>   * @nor:	pointer to 'struct spi_nor'.
>   * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
>   *		address mode.
>   *
>   * Return: 0 on success, -errno otherwise.
>   */
> -static int macronix_set_4byte(struct spi_nor *nor, bool enable)
> +static int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable)


Sounds a bit weird, how about simplifying this to:

	spi_nor_set_4byte_addr_mode()

Or if you want to be specific:

	spi_nor_en_ex_4byte_addr_mode()

>  {
>  	int ret;
>  
> @@ -604,14 +605,15 @@ static int macronix_set_4byte(struct spi_nor *nor, bool enable)
>  }
>  
>  /**
> - * st_micron_set_4byte() - Set 4-byte address mode for ST and Micron flashes.
> + * spi_nor_en4_ex4_wen_set_4byte() - Set 4-byte address mode for ST and Micron
> + * flashes.
>   * @nor:	pointer to 'struct spi_nor'.
>   * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
>   *		address mode.
>   *
>   * Return: 0 on success, -errno otherwise.
>   */
> -static int st_micron_set_4byte(struct spi_nor *nor, bool enable)
> +static int spi_nor_en4_ex4_wen_set_4byte(struct spi_nor *nor, bool enable)


Unrelated to this patch itself, but can we just have one set_4byte
variant that uses WREN and drop the other one?
I expect sending WREN should be harmless even for cmds that don't expect
one.

Rest looks good to me.

Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>

-- 
Regards
Vignesh

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

* Re: [PATCH 02/23] mtd: spi-nor: Prepare core / manufacturer code split
  2020-03-02 18:07 ` [PATCH 02/23] mtd: spi-nor: Prepare core / manufacturer code split Tudor.Ambarus
@ 2020-03-13  6:08   ` Vignesh Raghavendra
  2020-03-13 14:41     ` Tudor.Ambarus
  0 siblings, 1 reply; 39+ messages in thread
From: Vignesh Raghavendra @ 2020-03-13  6:08 UTC (permalink / raw)
  To: Tudor.Ambarus, bbrezillon, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel



On 02/03/20 11:37 pm, Tudor.Ambarus@microchip.com wrote:
> From: Boris Brezillon <bbrezillon@kernel.org>
> 
> Move all SPI NOR controller drivers to a controllers/ sub-directory
> so that we only have SPI NOR related source files under
> drivers/mtd/spi-nor/.
> 
> Rename spi-nor.c into core.c, we are about to split this file in multiple
> source files (one per manufacturer, plus one for the SFDP parsing logic).
> 
> Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>


But there are at least two drivers being moved from spi-nor to spi/
which would conflict with this change.

Regards
Vignesh

> ---
>  drivers/mtd/spi-nor/Kconfig                   | 83 +------------------
>  drivers/mtd/spi-nor/Makefile                  | 10 +--
>  drivers/mtd/spi-nor/controllers/Kconfig       | 83 +++++++++++++++++++
>  drivers/mtd/spi-nor/controllers/Makefile      |  9 ++
>  .../spi-nor/{ => controllers}/aspeed-smc.c    |  0
>  .../{ => controllers}/cadence-quadspi.c       |  0
>  .../mtd/spi-nor/{ => controllers}/hisi-sfc.c  |  0
>  .../spi-nor/{ => controllers}/intel-spi-pci.c |  0
>  .../{ => controllers}/intel-spi-platform.c    |  0
>  .../mtd/spi-nor/{ => controllers}/intel-spi.c |  0
>  .../mtd/spi-nor/{ => controllers}/intel-spi.h |  0
>  .../spi-nor/{ => controllers}/mtk-quadspi.c   |  0
>  .../mtd/spi-nor/{ => controllers}/nxp-spifi.c |  0
>  drivers/mtd/spi-nor/{spi-nor.c => core.c}     |  0
>  14 files changed, 95 insertions(+), 90 deletions(-)
>  create mode 100644 drivers/mtd/spi-nor/controllers/Kconfig
>  create mode 100644 drivers/mtd/spi-nor/controllers/Makefile
>  rename drivers/mtd/spi-nor/{ => controllers}/aspeed-smc.c (100%)
>  rename drivers/mtd/spi-nor/{ => controllers}/cadence-quadspi.c (100%)
>  rename drivers/mtd/spi-nor/{ => controllers}/hisi-sfc.c (100%)
>  rename drivers/mtd/spi-nor/{ => controllers}/intel-spi-pci.c (100%)
>  rename drivers/mtd/spi-nor/{ => controllers}/intel-spi-platform.c (100%)
>  rename drivers/mtd/spi-nor/{ => controllers}/intel-spi.c (100%)
>  rename drivers/mtd/spi-nor/{ => controllers}/intel-spi.h (100%)
>  rename drivers/mtd/spi-nor/{ => controllers}/mtk-quadspi.c (100%)
>  rename drivers/mtd/spi-nor/{ => controllers}/nxp-spifi.c (100%)
>  rename drivers/mtd/spi-nor/{spi-nor.c => core.c} (100%)
> 
> diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
> index c1eda67d1ad2..6e816eafb312 100644
> --- a/drivers/mtd/spi-nor/Kconfig
> +++ b/drivers/mtd/spi-nor/Kconfig
> @@ -24,87 +24,6 @@ config MTD_SPI_NOR_USE_4K_SECTORS
>  	  Please note that some tools/drivers/filesystems may not work with
>  	  4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum).
>  
> -config SPI_ASPEED_SMC
> -	tristate "Aspeed flash controllers in SPI mode"
> -	depends on ARCH_ASPEED || COMPILE_TEST
> -	depends on HAS_IOMEM && OF
> -	help
> -	  This enables support for the Firmware Memory controller (FMC)
> -	  in the Aspeed AST2500/AST2400 SoCs when attached to SPI NOR chips,
> -	  and support for the SPI flash memory controller (SPI) for
> -	  the host firmware. The implementation only supports SPI NOR.
> -
> -config SPI_CADENCE_QUADSPI
> -	tristate "Cadence Quad SPI controller"
> -	depends on OF && (ARM || ARM64 || COMPILE_TEST)
> -	help
> -	  Enable support for the Cadence Quad SPI Flash controller.
> -
> -	  Cadence QSPI is a specialized controller for connecting an SPI
> -	  Flash over 1/2/4-bit wide bus. Enable this option if you have a
> -	  device with a Cadence QSPI controller and want to access the
> -	  Flash as an MTD device.
> -
> -config SPI_HISI_SFC
> -	tristate "Hisilicon FMC SPI-NOR Flash Controller(SFC)"
> -	depends on ARCH_HISI || COMPILE_TEST
> -	depends on HAS_IOMEM
> -	help
> -	  This enables support for HiSilicon FMC SPI-NOR flash controller.
> -
> -config SPI_MTK_QUADSPI
> -	tristate "MediaTek Quad SPI controller"
> -	depends on HAS_IOMEM
> -	help
> -	  This enables support for the Quad SPI controller in master mode.
> -	  This controller does not support generic SPI. It only supports
> -	  SPI NOR.
> -
> -config SPI_NXP_SPIFI
> -	tristate "NXP SPI Flash Interface (SPIFI)"
> -	depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
> -	depends on HAS_IOMEM
> -	help
> -	  Enable support for the NXP LPC SPI Flash Interface controller.
> -
> -	  SPIFI is a specialized controller for connecting serial SPI
> -	  Flash. Enable this option if you have a device with a SPIFI
> -	  controller and want to access the Flash as a mtd device.
> -
> -config SPI_INTEL_SPI
> -	tristate
> -
> -config SPI_INTEL_SPI_PCI
> -	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
> -	depends on X86 && PCI
> -	select SPI_INTEL_SPI
> -	help
> -	  This enables PCI support for the Intel PCH/PCU SPI controller in
> -	  master mode. This controller is present in modern Intel hardware
> -	  and is used to hold BIOS and other persistent settings. Using
> -	  this driver it is possible to upgrade BIOS directly from Linux.
> -
> -	  Say N here unless you know what you are doing. Overwriting the
> -	  SPI flash may render the system unbootable.
> -
> -	  To compile this driver as a module, choose M here: the module
> -	  will be called intel-spi-pci.
> -
> -config SPI_INTEL_SPI_PLATFORM
> -	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
> -	depends on X86
> -	select SPI_INTEL_SPI
> -	help
> -	  This enables platform support for the Intel PCH/PCU SPI
> -	  controller in master mode. This controller is present in modern
> -	  Intel hardware and is used to hold BIOS and other persistent
> -	  settings. Using this driver it is possible to upgrade BIOS
> -	  directly from Linux.
> -
> -	  Say N here unless you know what you are doing. Overwriting the
> -	  SPI flash may render the system unbootable.
> -
> -	  To compile this driver as a module, choose M here: the module
> -	  will be called intel-spi-platform.
> +source "drivers/mtd/spi-nor/controllers/Kconfig"
>  
>  endif # MTD_SPI_NOR
> diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
> index 9c5ed03cdc19..d6fc70ab4a32 100644
> --- a/drivers/mtd/spi-nor/Makefile
> +++ b/drivers/mtd/spi-nor/Makefile
> @@ -1,10 +1,4 @@
>  # SPDX-License-Identifier: GPL-2.0
> +
> +spi-nor-objs			:= core.o
>  obj-$(CONFIG_MTD_SPI_NOR)	+= spi-nor.o
> -obj-$(CONFIG_SPI_ASPEED_SMC)	+= aspeed-smc.o
> -obj-$(CONFIG_SPI_CADENCE_QUADSPI)	+= cadence-quadspi.o
> -obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o
> -obj-$(CONFIG_SPI_MTK_QUADSPI)    += mtk-quadspi.o
> -obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
> -obj-$(CONFIG_SPI_INTEL_SPI)	+= intel-spi.o
> -obj-$(CONFIG_SPI_INTEL_SPI_PCI)	+= intel-spi-pci.o
> -obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)	+= intel-spi-platform.o
> diff --git a/drivers/mtd/spi-nor/controllers/Kconfig b/drivers/mtd/spi-nor/controllers/Kconfig
> new file mode 100644
> index 000000000000..a02feb201a5b
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/controllers/Kconfig
> @@ -0,0 +1,83 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config SPI_ASPEED_SMC
> +	tristate "Aspeed flash controllers in SPI mode"
> +	depends on ARCH_ASPEED || COMPILE_TEST
> +	depends on HAS_IOMEM && OF
> +	help
> +	  This enables support for the Firmware Memory controller (FMC)
> +	  in the Aspeed AST2500/AST2400 SoCs when attached to SPI NOR chips,
> +	  and support for the SPI flash memory controller (SPI) for
> +	  the host firmware. The implementation only supports SPI NOR.
> +
> +config SPI_CADENCE_QUADSPI
> +	tristate "Cadence Quad SPI controller"
> +	depends on OF && (ARM || ARM64 || COMPILE_TEST)
> +	help
> +	  Enable support for the Cadence Quad SPI Flash controller.
> +
> +	  Cadence QSPI is a specialized controller for connecting an SPI
> +	  Flash over 1/2/4-bit wide bus. Enable this option if you have a
> +	  device with a Cadence QSPI controller and want to access the
> +	  Flash as an MTD device.
> +
> +config SPI_HISI_SFC
> +	tristate "Hisilicon FMC SPI-NOR Flash Controller(SFC)"
> +	depends on ARCH_HISI || COMPILE_TEST
> +	depends on HAS_IOMEM
> +	help
> +	  This enables support for HiSilicon FMC SPI-NOR flash controller.
> +
> +config SPI_MTK_QUADSPI
> +	tristate "MediaTek Quad SPI controller"
> +	depends on HAS_IOMEM
> +	help
> +	  This enables support for the Quad SPI controller in master mode.
> +	  This controller does not support generic SPI. It only supports
> +	  SPI NOR.
> +
> +config SPI_NXP_SPIFI
> +	tristate "NXP SPI Flash Interface (SPIFI)"
> +	depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
> +	depends on HAS_IOMEM
> +	help
> +	  Enable support for the NXP LPC SPI Flash Interface controller.
> +
> +	  SPIFI is a specialized controller for connecting serial SPI
> +	  Flash. Enable this option if you have a device with a SPIFI
> +	  controller and want to access the Flash as a mtd device.
> +
> +config SPI_INTEL_SPI
> +	tristate
> +
> +config SPI_INTEL_SPI_PCI
> +	tristate "Intel PCH/PCU SPI flash PCI driver (DANGEROUS)"
> +	depends on X86 && PCI
> +	select SPI_INTEL_SPI
> +	help
> +	  This enables PCI support for the Intel PCH/PCU SPI controller in
> +	  master mode. This controller is present in modern Intel hardware
> +	  and is used to hold BIOS and other persistent settings. Using
> +	  this driver it is possible to upgrade BIOS directly from Linux.
> +
> +	  Say N here unless you know what you are doing. Overwriting the
> +	  SPI flash may render the system unbootable.
> +
> +	  To compile this driver as a module, choose M here: the module
> +	  will be called intel-spi-pci.
> +
> +config SPI_INTEL_SPI_PLATFORM
> +	tristate "Intel PCH/PCU SPI flash platform driver (DANGEROUS)"
> +	depends on X86
> +	select SPI_INTEL_SPI
> +	help
> +	  This enables platform support for the Intel PCH/PCU SPI
> +	  controller in master mode. This controller is present in modern
> +	  Intel hardware and is used to hold BIOS and other persistent
> +	  settings. Using this driver it is possible to upgrade BIOS
> +	  directly from Linux.
> +
> +	  Say N here unless you know what you are doing. Overwriting the
> +	  SPI flash may render the system unbootable.
> +
> +	  To compile this driver as a module, choose M here: the module
> +	  will be called intel-spi-platform.
> diff --git a/drivers/mtd/spi-nor/controllers/Makefile b/drivers/mtd/spi-nor/controllers/Makefile
> new file mode 100644
> index 000000000000..c9a39992d63d
> --- /dev/null
> +++ b/drivers/mtd/spi-nor/controllers/Makefile
> @@ -0,0 +1,9 @@
> +# SPDX-License-Identifier: GPL-2.0
> +obj-$(CONFIG_SPI_ASPEED_SMC)	+= aspeed-smc.o
> +obj-$(CONFIG_SPI_CADENCE_QUADSPI)	+= cadence-quadspi.o
> +obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o
> +obj-$(CONFIG_SPI_MTK_QUADSPI)    += mtk-quadspi.o
> +obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
> +obj-$(CONFIG_SPI_INTEL_SPI)	+= intel-spi.o
> +obj-$(CONFIG_SPI_INTEL_SPI_PCI)	+= intel-spi-pci.o
> +obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)	+= intel-spi-platform.o
> diff --git a/drivers/mtd/spi-nor/aspeed-smc.c b/drivers/mtd/spi-nor/controllers/aspeed-smc.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/aspeed-smc.c
> rename to drivers/mtd/spi-nor/controllers/aspeed-smc.c
> diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/controllers/cadence-quadspi.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/cadence-quadspi.c
> rename to drivers/mtd/spi-nor/controllers/cadence-quadspi.c
> diff --git a/drivers/mtd/spi-nor/hisi-sfc.c b/drivers/mtd/spi-nor/controllers/hisi-sfc.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/hisi-sfc.c
> rename to drivers/mtd/spi-nor/controllers/hisi-sfc.c
> diff --git a/drivers/mtd/spi-nor/intel-spi-pci.c b/drivers/mtd/spi-nor/controllers/intel-spi-pci.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/intel-spi-pci.c
> rename to drivers/mtd/spi-nor/controllers/intel-spi-pci.c
> diff --git a/drivers/mtd/spi-nor/intel-spi-platform.c b/drivers/mtd/spi-nor/controllers/intel-spi-platform.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/intel-spi-platform.c
> rename to drivers/mtd/spi-nor/controllers/intel-spi-platform.c
> diff --git a/drivers/mtd/spi-nor/intel-spi.c b/drivers/mtd/spi-nor/controllers/intel-spi.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/intel-spi.c
> rename to drivers/mtd/spi-nor/controllers/intel-spi.c
> diff --git a/drivers/mtd/spi-nor/intel-spi.h b/drivers/mtd/spi-nor/controllers/intel-spi.h
> similarity index 100%
> rename from drivers/mtd/spi-nor/intel-spi.h
> rename to drivers/mtd/spi-nor/controllers/intel-spi.h
> diff --git a/drivers/mtd/spi-nor/mtk-quadspi.c b/drivers/mtd/spi-nor/controllers/mtk-quadspi.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/mtk-quadspi.c
> rename to drivers/mtd/spi-nor/controllers/mtk-quadspi.c
> diff --git a/drivers/mtd/spi-nor/nxp-spifi.c b/drivers/mtd/spi-nor/controllers/nxp-spifi.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/nxp-spifi.c
> rename to drivers/mtd/spi-nor/controllers/nxp-spifi.c
> diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/core.c
> similarity index 100%
> rename from drivers/mtd/spi-nor/spi-nor.c
> rename to drivers/mtd/spi-nor/core.c
> 

-- 
Regards
Vignesh

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

* Re: [PATCH 04/23] mtd: spi-nor: Expose stuctures and functions to manufacturer drivers
  2020-03-02 18:07 ` [PATCH 04/23] mtd: spi-nor: Expose stuctures and functions to manufacturer drivers Tudor.Ambarus
@ 2020-03-13  6:38   ` Vignesh Raghavendra
  0 siblings, 0 replies; 39+ messages in thread
From: Vignesh Raghavendra @ 2020-03-13  6:38 UTC (permalink / raw)
  To: Tudor.Ambarus, bbrezillon, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel



On 02/03/20 11:37 pm, Tudor.Ambarus@microchip.com wrote:
> From: Boris Brezillon <bbrezillon@kernel.org>
> 
> Expose the flash_info struct and the generic set_4byte() implementations.
> Some manufacturers rely on the generic set_4byte() implementations.
> Remove the static specifier and expose their prototypes in core.h.
> 
> Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>

-- 
Regards
Vignesh

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

* Re: [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h
  2020-03-02 18:07 ` [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h Tudor.Ambarus
  2020-03-07 14:49   ` Boris Brezillon
@ 2020-03-13  8:13   ` Vignesh Raghavendra
  2020-03-13  8:27     ` Tudor.Ambarus
  1 sibling, 1 reply; 39+ messages in thread
From: Vignesh Raghavendra @ 2020-03-13  8:13 UTC (permalink / raw)
  To: Tudor.Ambarus, bbrezillon, linux-mtd
  Cc: miquel.raynal, richard, joel, andrew, Nicolas.Ferre,
	alexandre.belloni, Ludovic.Desroches, matthias.bgg, vz,
	michal.simek, ludovic.barre, john.garry, tglx, nishkadg.linux,
	michael, dinguyen, thor.thayer, swboyd, opensource,
	mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel



On 02/03/20 11:37 pm, Tudor.Ambarus@microchip.com wrote:
> From: Tudor Ambarus <tudor.ambarus@microchip.com>
> 
> The SPI NOR controllers drivers must not be able to use structures that
> are meant just for the SPI NOR core.
> 
> struct spi_nor_flash_parameter is filled at run-time with info gathered
> from flash_info, manufacturer and sfdp data. struct spi_nor_flash_parameter
> should be opaque to the SPI NOR controller drivers, make sure it is.
> 
> spi_nor_option_flags, spi_nor_read_command, spi_nor_pp_command,
> spi_nor_read_command_index and spi_nor_pp_command_index are defined for the
> core use, make sure they are opaque to the SPI NOR controller drivers.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

Nice work!

Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>

Should we drop SNOR_MFR_* macros as well or do you see a neeed for them?


> ---
>  drivers/mtd/spi-nor/core.c       |  86 ++++++----
>  drivers/mtd/spi-nor/core.h       | 214 +++++++++++++++++++++++++
>  drivers/mtd/spi-nor/gigadevice.c |   2 +-
>  drivers/mtd/spi-nor/issi.c       |   2 +-
>  drivers/mtd/spi-nor/macronix.c   |   4 +-
>  drivers/mtd/spi-nor/micron-st.c  |   4 +-
>  drivers/mtd/spi-nor/sfdp.c       |  10 ++
>  drivers/mtd/spi-nor/spansion.c   |   2 +-
>  drivers/mtd/spi-nor/winbond.c    |   2 +-
>  drivers/mtd/spi-nor/xilinx.c     |   4 +-
>  include/linux/mtd/spi-nor.h      | 259 +------------------------------
>  11 files changed, 294 insertions(+), 295 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index a2e1917b608d..860dac1dff90 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -802,7 +802,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
>  		ret = spi_nor_read_cr(nor, &sr_cr[1]);
>  		if (ret)
>  			return ret;
> -	} else if (nor->params.quad_enable) {
> +	} else if (nor->params->quad_enable) {
>  		/*
>  		 * If the Status Register 2 Read command (35h) is not
>  		 * supported, we should at least be sure we don't
> @@ -810,7 +810,7 @@ static int spi_nor_write_16bit_sr_and_check(struct spi_nor *nor, u8 sr1)
>  		 *
>  		 * We can safely assume that when the Quad Enable method is
>  		 * set, the value of the QE bit is one, as a consequence of the
> -		 * nor->params.quad_enable() call.
> +		 * nor->params->quad_enable() call.
>  		 *
>  		 * We can safely assume that the Quad Enable bit is present in
>  		 * the Status Register 2 at BIT(1). According to the JESD216
> @@ -1075,6 +1075,11 @@ static u8 spi_nor_convert_3to4_erase(u8 opcode)
>  				      ARRAY_SIZE(spi_nor_3to4_erase));
>  }
>  
> +static bool spi_nor_has_uniform_erase(const struct spi_nor *nor)
> +{
> +	return !!nor->params->erase_map.uniform_erase_type;
> +}
> +
>  static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
>  {
>  	nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
> @@ -1082,7 +1087,7 @@ static void spi_nor_set_4byte_opcodes(struct spi_nor *nor)
>  	nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
>  
>  	if (!spi_nor_has_uniform_erase(nor)) {
> -		struct spi_nor_erase_map *map = &nor->params.erase_map;
> +		struct spi_nor_erase_map *map = &nor->params->erase_map;
>  		struct spi_nor_erase_type *erase;
>  		int i;
>  
> @@ -1119,10 +1124,10 @@ void spi_nor_unlock_and_unprep(struct spi_nor *nor)
>  
>  static u32 spi_nor_convert_addr(struct spi_nor *nor, loff_t addr)
>  {
> -	if (!nor->params.convert_addr)
> +	if (!nor->params->convert_addr)
>  		return addr;
>  
> -	return nor->params.convert_addr(nor, addr);
> +	return nor->params->convert_addr(nor, addr);
>  }
>  
>  /*
> @@ -1227,6 +1232,16 @@ spi_nor_find_best_erase_type(const struct spi_nor_erase_map *map,
>  	return NULL;
>  }
>  
> +static u64 spi_nor_region_is_last(const struct spi_nor_erase_region *region)
> +{
> +	return region->offset & SNOR_LAST_REGION;
> +}
> +
> +static u64 spi_nor_region_end(const struct spi_nor_erase_region *region)
> +{
> +	return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
> +}
> +
>  /**
>   * spi_nor_region_next() - get the next spi nor region
>   * @region:	pointer to a structure that describes a SPI NOR erase region
> @@ -1331,7 +1346,7 @@ static int spi_nor_init_erase_cmd_list(struct spi_nor *nor,
>  				       struct list_head *erase_list,
>  				       u64 addr, u32 len)
>  {
> -	const struct spi_nor_erase_map *map = &nor->params.erase_map;
> +	const struct spi_nor_erase_map *map = &nor->params->erase_map;
>  	const struct spi_nor_erase_type *erase, *prev_erase = NULL;
>  	struct spi_nor_erase_region *region;
>  	struct spi_nor_erase_command *cmd = NULL;
> @@ -1817,7 +1832,7 @@ static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  	if (ret)
>  		return ret;
>  
> -	ret = nor->params.locking_ops->lock(nor, ofs, len);
> +	ret = nor->params->locking_ops->lock(nor, ofs, len);
>  
>  	spi_nor_unlock_and_unprep(nor);
>  	return ret;
> @@ -1832,7 +1847,7 @@ static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  	if (ret)
>  		return ret;
>  
> -	ret = nor->params.locking_ops->unlock(nor, ofs, len);
> +	ret = nor->params->locking_ops->unlock(nor, ofs, len);
>  
>  	spi_nor_unlock_and_unprep(nor);
>  	return ret;
> @@ -1847,7 +1862,7 @@ static int spi_nor_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
>  	if (ret)
>  		return ret;
>  
> -	ret = nor->params.locking_ops->is_locked(nor, ofs, len);
> +	ret = nor->params->locking_ops->is_locked(nor, ofs, len);
>  
>  	spi_nor_unlock_and_unprep(nor);
>  	return ret;
> @@ -2312,7 +2327,7 @@ static int spi_nor_spimem_check_pp(struct spi_nor *nor,
>  static void
>  spi_nor_spimem_adjust_hwcaps(struct spi_nor *nor, u32 *hwcaps)
>  {
> -	struct spi_nor_flash_parameter *params =  &nor->params;
> +	struct spi_nor_flash_parameter *params = nor->params;
>  	unsigned int cap;
>  
>  	/* DTR modes are not supported yet, mask them all. */
> @@ -2411,7 +2426,7 @@ static int spi_nor_select_read(struct spi_nor *nor,
>  	if (cmd < 0)
>  		return -EINVAL;
>  
> -	read = &nor->params.reads[cmd];
> +	read = &nor->params->reads[cmd];
>  	nor->read_opcode = read->opcode;
>  	nor->read_proto = read->proto;
>  
> @@ -2442,7 +2457,7 @@ static int spi_nor_select_pp(struct spi_nor *nor,
>  	if (cmd < 0)
>  		return -EINVAL;
>  
> -	pp = &nor->params.page_programs[cmd];
> +	pp = &nor->params->page_programs[cmd];
>  	nor->program_opcode = pp->opcode;
>  	nor->write_proto = pp->proto;
>  	return 0;
> @@ -2503,7 +2518,7 @@ spi_nor_select_uniform_erase(struct spi_nor_erase_map *map,
>  
>  static int spi_nor_select_erase(struct spi_nor *nor)
>  {
> -	struct spi_nor_erase_map *map = &nor->params.erase_map;
> +	struct spi_nor_erase_map *map = &nor->params->erase_map;
>  	const struct spi_nor_erase_type *erase = NULL;
>  	struct mtd_info *mtd = &nor->mtd;
>  	u32 wanted_size = nor->info->sector_size;
> @@ -2552,7 +2567,7 @@ static int spi_nor_select_erase(struct spi_nor *nor)
>  static int spi_nor_default_setup(struct spi_nor *nor,
>  				 const struct spi_nor_hwcaps *hwcaps)
>  {
> -	struct spi_nor_flash_parameter *params = &nor->params;
> +	struct spi_nor_flash_parameter *params = nor->params;
>  	u32 ignored_mask, shared_mask;
>  	int err;
>  
> @@ -2613,10 +2628,10 @@ static int spi_nor_default_setup(struct spi_nor *nor,
>  static int spi_nor_setup(struct spi_nor *nor,
>  			 const struct spi_nor_hwcaps *hwcaps)
>  {
> -	if (!nor->params.setup)
> +	if (!nor->params->setup)
>  		return 0;
>  
> -	return nor->params.setup(nor, hwcaps);
> +	return nor->params->setup(nor, hwcaps);
>  }
>  
>  /**
> @@ -2646,13 +2661,13 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
>  {
>  	struct spi_nor_flash_parameter sfdp_params;
>  
> -	memcpy(&sfdp_params, &nor->params, sizeof(sfdp_params));
> +	memcpy(&sfdp_params, nor->params, sizeof(sfdp_params));
>  
>  	if (spi_nor_parse_sfdp(nor, &sfdp_params)) {
>  		nor->addr_width = 0;
>  		nor->flags &= ~SNOR_F_4B_OPCODES;
>  	} else {
> -		memcpy(&nor->params, &sfdp_params, sizeof(nor->params));
> +		memcpy(nor->params, &sfdp_params, sizeof(*nor->params));
>  	}
>  }
>  
> @@ -2663,7 +2678,7 @@ static void spi_nor_sfdp_init_params(struct spi_nor *nor)
>   */
>  static void spi_nor_info_init_params(struct spi_nor *nor)
>  {
> -	struct spi_nor_flash_parameter *params = &nor->params;
> +	struct spi_nor_flash_parameter *params = nor->params;
>  	struct spi_nor_erase_map *map = &params->erase_map;
>  	const struct flash_info *info = nor->info;
>  	struct device_node *np = spi_nor_get_flash_node(nor);
> @@ -2782,8 +2797,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
>  	 * NOR protection support. When locking_ops are not provided, we pick
>  	 * the default ones.
>  	 */
> -	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params.locking_ops)
> -		nor->params.locking_ops = &spi_nor_sr_locking_ops;
> +	if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops)
> +		nor->params->locking_ops = &spi_nor_sr_locking_ops;
>  }
>  
>  /**
> @@ -2823,8 +2838,12 @@ static void spi_nor_late_init_params(struct spi_nor *nor)
>   * ->default_init() hook or the SFDP parser do not set specific params.
>   *		spi_nor_late_init_params()
>   */
> -static void spi_nor_init_params(struct spi_nor *nor)
> +static int spi_nor_init_params(struct spi_nor *nor)
>  {
> +	nor->params = devm_kzalloc(nor->dev, sizeof(*nor->params), GFP_KERNEL);
> +	if (!nor->params)
> +		return -ENOMEM;
> +
>  	spi_nor_info_init_params(nor);
>  
>  	spi_nor_manufacturer_init_params(nor);
> @@ -2836,6 +2855,8 @@ static void spi_nor_init_params(struct spi_nor *nor)
>  	spi_nor_post_sfdp_fixups(nor);
>  
>  	spi_nor_late_init_params(nor);
> +
> +	return 0;
>  }
>  
>  /**
> @@ -2846,14 +2867,14 @@ static void spi_nor_init_params(struct spi_nor *nor)
>   */
>  static int spi_nor_quad_enable(struct spi_nor *nor)
>  {
> -	if (!nor->params.quad_enable)
> +	if (!nor->params->quad_enable)
>  		return 0;
>  
>  	if (!(spi_nor_get_protocol_width(nor->read_proto) == 4 ||
>  	      spi_nor_get_protocol_width(nor->write_proto) == 4))
>  		return 0;
>  
> -	return nor->params.quad_enable(nor);
> +	return nor->params->quad_enable(nor);
>  }
>  
>  /**
> @@ -2868,7 +2889,7 @@ static int spi_nor_quad_enable(struct spi_nor *nor)
>  static int spi_nor_unlock_all(struct spi_nor *nor)
>  {
>  	if (nor->flags & SNOR_F_HAS_LOCK)
> -		return spi_nor_unlock(&nor->mtd, 0, nor->params.size);
> +		return spi_nor_unlock(&nor->mtd, 0, nor->params->size);
>  
>  	return 0;
>  }
> @@ -2899,7 +2920,7 @@ static int spi_nor_init(struct spi_nor *nor)
>  		 */
>  		WARN_ONCE(nor->flags & SNOR_F_BROKEN_RESET,
>  			  "enabling reset hack; may not recover from unexpected reboots\n");
> -		nor->params.set_4byte(nor, true);
> +		nor->params->set_4byte(nor, true);
>  	}
>  
>  	return 0;
> @@ -2923,7 +2944,7 @@ void spi_nor_restore(struct spi_nor *nor)
>  	/* restore the addressing mode */
>  	if (nor->addr_width == 4 && !(nor->flags & SNOR_F_4B_OPCODES) &&
>  	    nor->flags & SNOR_F_BROKEN_RESET)
> -		nor->params.set_4byte(nor, false);
> +		nor->params->set_4byte(nor, false);
>  }
>  EXPORT_SYMBOL_GPL(spi_nor_restore);
>  
> @@ -3028,7 +3049,6 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>  	struct device *dev = nor->dev;
>  	struct mtd_info *mtd = &nor->mtd;
>  	struct device_node *np = spi_nor_get_flash_node(nor);
> -	struct spi_nor_flash_parameter *params = &nor->params;
>  	int ret;
>  	int i;
>  
> @@ -3079,7 +3099,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>  	mtd->_write = spi_nor_write;
>  
>  	/* Init flash parameters based on flash_info struct and SFDP */
> -	spi_nor_init_params(nor);
> +	ret = spi_nor_init_params(nor);
> +	if (ret)
> +		return ret;
>  
>  	if (!mtd->name)
>  		mtd->name = dev_name(dev);
> @@ -3087,12 +3109,12 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>  	mtd->type = MTD_NORFLASH;
>  	mtd->writesize = 1;
>  	mtd->flags = MTD_CAP_NORFLASH;
> -	mtd->size = params->size;
> +	mtd->size = nor->params->size;
>  	mtd->_erase = spi_nor_erase;
>  	mtd->_read = spi_nor_read;
>  	mtd->_resume = spi_nor_resume;
>  
> -	if (nor->params.locking_ops) {
> +	if (nor->params->locking_ops) {
>  		mtd->_lock = spi_nor_lock;
>  		mtd->_unlock = spi_nor_unlock;
>  		mtd->_is_locked = spi_nor_is_locked;
> @@ -3115,7 +3137,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
>  		mtd->flags |= MTD_NO_ERASE;
>  
>  	mtd->dev.parent = dev;
> -	nor->page_size = params->page_size;
> +	nor->page_size = nor->params->page_size;
>  	mtd->writebufsize = nor->page_size;
>  
>  	if (of_property_read_bool(np, "broken-flash-reset"))
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 3541a84c03d8..7654b6f3b966 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -11,6 +11,220 @@
>  
>  #define SPI_NOR_MAX_ID_LEN	6
>  
> +enum spi_nor_option_flags {
> +	SNOR_F_USE_FSR		= BIT(0),
> +	SNOR_F_HAS_SR_TB	= BIT(1),
> +	SNOR_F_NO_OP_CHIP_ERASE	= BIT(2),
> +	SNOR_F_READY_XSR_RDY	= BIT(3),
> +	SNOR_F_USE_CLSR		= BIT(4),
> +	SNOR_F_BROKEN_RESET	= BIT(5),
> +	SNOR_F_4B_OPCODES	= BIT(6),
> +	SNOR_F_HAS_4BAIT	= BIT(7),
> +	SNOR_F_HAS_LOCK		= BIT(8),
> +	SNOR_F_HAS_16BIT_SR	= BIT(9),
> +	SNOR_F_NO_READ_CR	= BIT(10),
> +	SNOR_F_HAS_SR_TB_BIT6	= BIT(11),
> +};
> +
> +struct spi_nor_read_command {
> +	u8			num_mode_clocks;
> +	u8			num_wait_states;
> +	u8			opcode;
> +	enum spi_nor_protocol	proto;
> +};
> +
> +struct spi_nor_pp_command {
> +	u8			opcode;
> +	enum spi_nor_protocol	proto;
> +};
> +
> +enum spi_nor_read_command_index {
> +	SNOR_CMD_READ,
> +	SNOR_CMD_READ_FAST,
> +	SNOR_CMD_READ_1_1_1_DTR,
> +
> +	/* Dual SPI */
> +	SNOR_CMD_READ_1_1_2,
> +	SNOR_CMD_READ_1_2_2,
> +	SNOR_CMD_READ_2_2_2,
> +	SNOR_CMD_READ_1_2_2_DTR,
> +
> +	/* Quad SPI */
> +	SNOR_CMD_READ_1_1_4,
> +	SNOR_CMD_READ_1_4_4,
> +	SNOR_CMD_READ_4_4_4,
> +	SNOR_CMD_READ_1_4_4_DTR,
> +
> +	/* Octal SPI */
> +	SNOR_CMD_READ_1_1_8,
> +	SNOR_CMD_READ_1_8_8,
> +	SNOR_CMD_READ_8_8_8,
> +	SNOR_CMD_READ_1_8_8_DTR,
> +
> +	SNOR_CMD_READ_MAX
> +};
> +
> +enum spi_nor_pp_command_index {
> +	SNOR_CMD_PP,
> +
> +	/* Quad SPI */
> +	SNOR_CMD_PP_1_1_4,
> +	SNOR_CMD_PP_1_4_4,
> +	SNOR_CMD_PP_4_4_4,
> +
> +	/* Octal SPI */
> +	SNOR_CMD_PP_1_1_8,
> +	SNOR_CMD_PP_1_8_8,
> +	SNOR_CMD_PP_8_8_8,
> +
> +	SNOR_CMD_PP_MAX
> +};
> +
> +/**
> + * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
> + * @size:		the size of the sector/block erased by the erase type.
> + *			JEDEC JESD216B imposes erase sizes to be a power of 2.
> + * @size_shift:		@size is a power of 2, the shift is stored in
> + *			@size_shift.
> + * @size_mask:		the size mask based on @size_shift.
> + * @opcode:		the SPI command op code to erase the sector/block.
> + * @idx:		Erase Type index as sorted in the Basic Flash Parameter
> + *			Table. It will be used to synchronize the supported
> + *			Erase Types with the ones identified in the SFDP
> + *			optional tables.
> + */
> +struct spi_nor_erase_type {
> +	u32	size;
> +	u32	size_shift;
> +	u32	size_mask;
> +	u8	opcode;
> +	u8	idx;
> +};
> +
> +/**
> + * struct spi_nor_erase_command - Used for non-uniform erases
> + * The structure is used to describe a list of erase commands to be executed
> + * once we validate that the erase can be performed. The elements in the list
> + * are run-length encoded.
> + * @list:		for inclusion into the list of erase commands.
> + * @count:		how many times the same erase command should be
> + *			consecutively used.
> + * @size:		the size of the sector/block erased by the command.
> + * @opcode:		the SPI command op code to erase the sector/block.
> + */
> +struct spi_nor_erase_command {
> +	struct list_head	list;
> +	u32			count;
> +	u32			size;
> +	u8			opcode;
> +};
> +
> +/**
> + * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
> + * @offset:		the offset in the data array of erase region start.
> + *			LSB bits are used as a bitmask encoding flags to
> + *			determine if this region is overlaid, if this region is
> + *			the last in the SPI NOR flash memory and to indicate
> + *			all the supported erase commands inside this region.
> + *			The erase types are sorted in ascending order with the
> + *			smallest Erase Type size being at BIT(0).
> + * @size:		the size of the region in bytes.
> + */
> +struct spi_nor_erase_region {
> +	u64		offset;
> +	u64		size;
> +};
> +
> +#define SNOR_ERASE_TYPE_MAX	4
> +#define SNOR_ERASE_TYPE_MASK	GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
> +
> +#define SNOR_LAST_REGION	BIT(4)
> +#define SNOR_OVERLAID_REGION	BIT(5)
> +
> +#define SNOR_ERASE_FLAGS_MAX	6
> +#define SNOR_ERASE_FLAGS_MASK	GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
> +
> +/**
> + * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
> + * @regions:		array of erase regions. The regions are consecutive in
> + *			address space. Walking through the regions is done
> + *			incrementally.
> + * @uniform_region:	a pre-allocated erase region for SPI NOR with a uniform
> + *			sector size (legacy implementation).
> + * @erase_type:		an array of erase types shared by all the regions.
> + *			The erase types are sorted in ascending order, with the
> + *			smallest Erase Type size being the first member in the
> + *			erase_type array.
> + * @uniform_erase_type:	bitmask encoding erase types that can erase the
> + *			entire memory. This member is completed at init by
> + *			uniform and non-uniform SPI NOR flash memories if they
> + *			support at least one erase type that can erase the
> + *			entire memory.
> + */
> +struct spi_nor_erase_map {
> +	struct spi_nor_erase_region	*regions;
> +	struct spi_nor_erase_region	uniform_region;
> +	struct spi_nor_erase_type	erase_type[SNOR_ERASE_TYPE_MAX];
> +	u8				uniform_erase_type;
> +};
> +
> +/**
> + * struct spi_nor_locking_ops - SPI NOR locking methods
> + * @lock:	lock a region of the SPI NOR.
> + * @unlock:	unlock a region of the SPI NOR.
> + * @is_locked:	check if a region of the SPI NOR is completely locked
> + */
> +struct spi_nor_locking_ops {
> +	int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> +	int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> +	int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> +};
> +
> +/**
> + * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
> + * Includes legacy flash parameters and settings that can be overwritten
> + * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
> + * Serial Flash Discoverable Parameters (SFDP) tables.
> + *
> + * @size:		the flash memory density in bytes.
> + * @page_size:		the page size of the SPI NOR flash memory.
> + * @hwcaps:		describes the read and page program hardware
> + *			capabilities.
> + * @reads:		read capabilities ordered by priority: the higher index
> + *                      in the array, the higher priority.
> + * @page_programs:	page program capabilities ordered by priority: the
> + *                      higher index in the array, the higher priority.
> + * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
> + *                      Table.
> + * @quad_enable:	enables SPI NOR quad mode.
> + * @set_4byte:		puts the SPI NOR in 4 byte addressing mode.
> + * @convert_addr:	converts an absolute address into something the flash
> + *                      will understand. Particularly useful when pagesize is
> + *                      not a power-of-2.
> + * @setup:              configures the SPI NOR memory. Useful for SPI NOR
> + *                      flashes that have peculiarities to the SPI NOR standard
> + *                      e.g. different opcodes, specific address calculation,
> + *                      page size, etc.
> + * @locking_ops:	SPI NOR locking methods.
> + */
> +struct spi_nor_flash_parameter {
> +	u64				size;
> +	u32				page_size;
> +
> +	struct spi_nor_hwcaps		hwcaps;
> +	struct spi_nor_read_command	reads[SNOR_CMD_READ_MAX];
> +	struct spi_nor_pp_command	page_programs[SNOR_CMD_PP_MAX];
> +
> +	struct spi_nor_erase_map        erase_map;
> +
> +	int (*quad_enable)(struct spi_nor *nor);
> +	int (*set_4byte)(struct spi_nor *nor, bool enable);
> +	u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
> +	int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
> +
> +	const struct spi_nor_locking_ops *locking_ops;
> +};
> +
>  /**
>   * struct spi_nor_fixups - SPI NOR fixup hooks
>   * @default_init: called after default flash parameters init. Used to tweak
> diff --git a/drivers/mtd/spi-nor/gigadevice.c b/drivers/mtd/spi-nor/gigadevice.c
> index 7930e4490dab..447d84bb2128 100644
> --- a/drivers/mtd/spi-nor/gigadevice.c
> +++ b/drivers/mtd/spi-nor/gigadevice.c
> @@ -16,7 +16,7 @@ static void gd25q256_default_init(struct spi_nor *nor)
>  	 * indicate the quad_enable method for this case, we need
>  	 * to set it in the default_init fixup hook.
>  	 */
> -	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> +	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
>  }
>  
>  static struct spi_nor_fixups gd25q256_fixups = {
> diff --git a/drivers/mtd/spi-nor/issi.c b/drivers/mtd/spi-nor/issi.c
> index 3a1c34c41388..ffcb60e54a80 100644
> --- a/drivers/mtd/spi-nor/issi.c
> +++ b/drivers/mtd/spi-nor/issi.c
> @@ -68,7 +68,7 @@ static const struct flash_info issi_parts[] = {
>  
>  static void issi_default_init(struct spi_nor *nor)
>  {
> -	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> +	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
>  }
>  
>  static const struct spi_nor_fixups issi_fixups = {
> diff --git a/drivers/mtd/spi-nor/macronix.c b/drivers/mtd/spi-nor/macronix.c
> index 1ae609c44676..d73bd0363144 100644
> --- a/drivers/mtd/spi-nor/macronix.c
> +++ b/drivers/mtd/spi-nor/macronix.c
> @@ -82,8 +82,8 @@ static const struct flash_info macronix_parts[] = {
>  
>  static void macronix_default_init(struct spi_nor *nor)
>  {
> -	nor->params.quad_enable = spi_nor_sr1_bit6_quad_enable;
> -	nor->params.set_4byte = spi_nor_en4_ex4_set_4byte;
> +	nor->params->quad_enable = spi_nor_sr1_bit6_quad_enable;
> +	nor->params->set_4byte = spi_nor_en4_ex4_set_4byte;
>  }
>  
>  static const struct spi_nor_fixups macronix_fixups = {
> diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
> index 8017ca58b3a5..5be817d2f27c 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -106,8 +106,8 @@ static void micron_st_default_init(struct spi_nor *nor)
>  {
>  	nor->flags |= SNOR_F_HAS_LOCK;
>  	nor->flags &= ~SNOR_F_HAS_16BIT_SR;
> -	nor->params.quad_enable = NULL;
> -	nor->params.set_4byte = spi_nor_en4_ex4_wen_set_4byte;
> +	nor->params->quad_enable = NULL;
> +	nor->params->set_4byte = spi_nor_en4_ex4_wen_set_4byte;
>  }
>  
>  static const struct spi_nor_fixups micron_st_fixups = {
> diff --git a/drivers/mtd/spi-nor/sfdp.c b/drivers/mtd/spi-nor/sfdp.c
> index b790c3ec871f..6829dc7e4f74 100644
> --- a/drivers/mtd/spi-nor/sfdp.c
> +++ b/drivers/mtd/spi-nor/sfdp.c
> @@ -734,6 +734,16 @@ static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt,
>  	return ret;
>  }
>  
> +static void spi_nor_region_mark_end(struct spi_nor_erase_region *region)
> +{
> +	region->offset |= SNOR_LAST_REGION;
> +}
> +
> +static void spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
> +{
> +	region->offset |= SNOR_OVERLAID_REGION;
> +}
> +
>  /**
>   * spi_nor_region_check_overlay() - set overlay bit when the region is overlaid
>   * @region:	pointer to a structure that describes a SPI NOR erase region
> diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
> index 16683983a20e..6756202ace4b 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -74,7 +74,7 @@ static const struct flash_info spansion_parts[] = {
>  
>  static void spansion_post_sfdp_fixups(struct spi_nor *nor)
>  {
> -	if (nor->params.size <= SZ_16M)
> +	if (nor->params->size <= SZ_16M)
>  		return;
>  
>  	nor->flags |= SNOR_F_4B_OPCODES;
> diff --git a/drivers/mtd/spi-nor/winbond.c b/drivers/mtd/spi-nor/winbond.c
> index 1e77dffbf729..f15be50024d1 100644
> --- a/drivers/mtd/spi-nor/winbond.c
> +++ b/drivers/mtd/spi-nor/winbond.c
> @@ -97,7 +97,7 @@ static int winbond_set_4byte(struct spi_nor *nor, bool enable)
>  
>  static void winbond_default_init(struct spi_nor *nor)
>  {
> -	nor->params.set_4byte = winbond_set_4byte;
> +	nor->params->set_4byte = winbond_set_4byte;
>  }
>  
>  static const struct spi_nor_fixups winbond_fixups = {
> diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
> index fcf635d89f65..1138bdbf4199 100644
> --- a/drivers/mtd/spi-nor/xilinx.c
> +++ b/drivers/mtd/spi-nor/xilinx.c
> @@ -70,7 +70,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
>  		nor->mtd.erasesize = 8 * nor->page_size;
>  	} else {
>  		/* Flash in Default addressing mode */
> -		nor->params.convert_addr = s3an_convert_addr;
> +		nor->params->convert_addr = s3an_convert_addr;
>  		nor->mtd.erasesize = nor->info->sector_size;
>  	}
>  
> @@ -79,7 +79,7 @@ static int xilinx_nor_setup(struct spi_nor *nor,
>  
>  static void xilinx_post_sfdp_fixups(struct spi_nor *nor)
>  {
> -	nor->params.setup = xilinx_nor_setup;
> +	nor->params->setup = xilinx_nor_setup;
>  }
>  
>  static const struct spi_nor_fixups xilinx_fixups = {
> diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
> index dde2988a809e..d3d34c4eea48 100644
> --- a/include/linux/mtd/spi-nor.h
> +++ b/include/linux/mtd/spi-nor.h
> @@ -227,110 +227,6 @@ static inline u8 spi_nor_get_protocol_width(enum spi_nor_protocol proto)
>  	return spi_nor_get_protocol_data_nbits(proto);
>  }
>  
> -enum spi_nor_option_flags {
> -	SNOR_F_USE_FSR		= BIT(0),
> -	SNOR_F_HAS_SR_TB	= BIT(1),
> -	SNOR_F_NO_OP_CHIP_ERASE	= BIT(2),
> -	SNOR_F_READY_XSR_RDY	= BIT(3),
> -	SNOR_F_USE_CLSR		= BIT(4),
> -	SNOR_F_BROKEN_RESET	= BIT(5),
> -	SNOR_F_4B_OPCODES	= BIT(6),
> -	SNOR_F_HAS_4BAIT	= BIT(7),
> -	SNOR_F_HAS_LOCK		= BIT(8),
> -	SNOR_F_HAS_16BIT_SR	= BIT(9),
> -	SNOR_F_NO_READ_CR	= BIT(10),
> -	SNOR_F_HAS_SR_TB_BIT6	= BIT(11),
> -
> -};
> -
> -/**
> - * struct spi_nor_erase_type - Structure to describe a SPI NOR erase type
> - * @size:		the size of the sector/block erased by the erase type.
> - *			JEDEC JESD216B imposes erase sizes to be a power of 2.
> - * @size_shift:		@size is a power of 2, the shift is stored in
> - *			@size_shift.
> - * @size_mask:		the size mask based on @size_shift.
> - * @opcode:		the SPI command op code to erase the sector/block.
> - * @idx:		Erase Type index as sorted in the Basic Flash Parameter
> - *			Table. It will be used to synchronize the supported
> - *			Erase Types with the ones identified in the SFDP
> - *			optional tables.
> - */
> -struct spi_nor_erase_type {
> -	u32	size;
> -	u32	size_shift;
> -	u32	size_mask;
> -	u8	opcode;
> -	u8	idx;
> -};
> -
> -/**
> - * struct spi_nor_erase_command - Used for non-uniform erases
> - * The structure is used to describe a list of erase commands to be executed
> - * once we validate that the erase can be performed. The elements in the list
> - * are run-length encoded.
> - * @list:		for inclusion into the list of erase commands.
> - * @count:		how many times the same erase command should be
> - *			consecutively used.
> - * @size:		the size of the sector/block erased by the command.
> - * @opcode:		the SPI command op code to erase the sector/block.
> - */
> -struct spi_nor_erase_command {
> -	struct list_head	list;
> -	u32			count;
> -	u32			size;
> -	u8			opcode;
> -};
> -
> -/**
> - * struct spi_nor_erase_region - Structure to describe a SPI NOR erase region
> - * @offset:		the offset in the data array of erase region start.
> - *			LSB bits are used as a bitmask encoding flags to
> - *			determine if this region is overlaid, if this region is
> - *			the last in the SPI NOR flash memory and to indicate
> - *			all the supported erase commands inside this region.
> - *			The erase types are sorted in ascending order with the
> - *			smallest Erase Type size being at BIT(0).
> - * @size:		the size of the region in bytes.
> - */
> -struct spi_nor_erase_region {
> -	u64		offset;
> -	u64		size;
> -};
> -
> -#define SNOR_ERASE_TYPE_MAX	4
> -#define SNOR_ERASE_TYPE_MASK	GENMASK_ULL(SNOR_ERASE_TYPE_MAX - 1, 0)
> -
> -#define SNOR_LAST_REGION	BIT(4)
> -#define SNOR_OVERLAID_REGION	BIT(5)
> -
> -#define SNOR_ERASE_FLAGS_MAX	6
> -#define SNOR_ERASE_FLAGS_MASK	GENMASK_ULL(SNOR_ERASE_FLAGS_MAX - 1, 0)
> -
> -/**
> - * struct spi_nor_erase_map - Structure to describe the SPI NOR erase map
> - * @regions:		array of erase regions. The regions are consecutive in
> - *			address space. Walking through the regions is done
> - *			incrementally.
> - * @uniform_region:	a pre-allocated erase region for SPI NOR with a uniform
> - *			sector size (legacy implementation).
> - * @erase_type:		an array of erase types shared by all the regions.
> - *			The erase types are sorted in ascending order, with the
> - *			smallest Erase Type size being the first member in the
> - *			erase_type array.
> - * @uniform_erase_type:	bitmask encoding erase types that can erase the
> - *			entire memory. This member is completed at init by
> - *			uniform and non-uniform SPI NOR flash memories if they
> - *			support at least one erase type that can erase the
> - *			entire memory.
> - */
> -struct spi_nor_erase_map {
> -	struct spi_nor_erase_region	*regions;
> -	struct spi_nor_erase_region	uniform_region;
> -	struct spi_nor_erase_type	erase_type[SNOR_ERASE_TYPE_MAX];
> -	u8				uniform_erase_type;
> -};
> -
>  /**
>   * struct spi_nor_hwcaps - Structure for describing the hardware capabilies
>   * supported by the SPI controller (bus master).
> @@ -406,61 +302,7 @@ struct spi_nor_hwcaps {
>  #define SNOR_HWCAPS_ALL		(SNOR_HWCAPS_READ_MASK |	\
>  				 SNOR_HWCAPS_PP_MASK)
>  
> -struct spi_nor_read_command {
> -	u8			num_mode_clocks;
> -	u8			num_wait_states;
> -	u8			opcode;
> -	enum spi_nor_protocol	proto;
> -};
> -
> -struct spi_nor_pp_command {
> -	u8			opcode;
> -	enum spi_nor_protocol	proto;
> -};
> -
> -enum spi_nor_read_command_index {
> -	SNOR_CMD_READ,
> -	SNOR_CMD_READ_FAST,
> -	SNOR_CMD_READ_1_1_1_DTR,
> -
> -	/* Dual SPI */
> -	SNOR_CMD_READ_1_1_2,
> -	SNOR_CMD_READ_1_2_2,
> -	SNOR_CMD_READ_2_2_2,
> -	SNOR_CMD_READ_1_2_2_DTR,
> -
> -	/* Quad SPI */
> -	SNOR_CMD_READ_1_1_4,
> -	SNOR_CMD_READ_1_4_4,
> -	SNOR_CMD_READ_4_4_4,
> -	SNOR_CMD_READ_1_4_4_DTR,
> -
> -	/* Octal SPI */
> -	SNOR_CMD_READ_1_1_8,
> -	SNOR_CMD_READ_1_8_8,
> -	SNOR_CMD_READ_8_8_8,
> -	SNOR_CMD_READ_1_8_8_DTR,
> -
> -	SNOR_CMD_READ_MAX
> -};
> -
> -enum spi_nor_pp_command_index {
> -	SNOR_CMD_PP,
> -
> -	/* Quad SPI */
> -	SNOR_CMD_PP_1_1_4,
> -	SNOR_CMD_PP_1_4_4,
> -	SNOR_CMD_PP_4_4_4,
> -
> -	/* Octal SPI */
> -	SNOR_CMD_PP_1_1_8,
> -	SNOR_CMD_PP_1_8_8,
> -	SNOR_CMD_PP_8_8_8,
> -
> -	SNOR_CMD_PP_MAX
> -};
> -
> -/* Forward declaration that will be used in 'struct spi_nor_flash_parameter' */
> +/* Forward declaration that is used in 'struct spi_nor_controller_ops' */
>  struct spi_nor;
>  
>  /**
> @@ -491,74 +333,14 @@ struct spi_nor_controller_ops {
>  	int (*erase)(struct spi_nor *nor, loff_t offs);
>  };
>  
> -/**
> - * struct spi_nor_locking_ops - SPI NOR locking methods
> - * @lock:	lock a region of the SPI NOR.
> - * @unlock:	unlock a region of the SPI NOR.
> - * @is_locked:	check if a region of the SPI NOR is completely locked
> - */
> -struct spi_nor_locking_ops {
> -	int (*lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> -	int (*unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> -	int (*is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
> -};
> -
> -/**
> - * struct spi_nor_flash_parameter - SPI NOR flash parameters and settings.
> - * Includes legacy flash parameters and settings that can be overwritten
> - * by the spi_nor_fixups hooks, or dynamically when parsing the JESD216
> - * Serial Flash Discoverable Parameters (SFDP) tables.
> - *
> - * @size:		the flash memory density in bytes.
> - * @page_size:		the page size of the SPI NOR flash memory.
> - * @hwcaps:		describes the read and page program hardware
> - *			capabilities.
> - * @reads:		read capabilities ordered by priority: the higher index
> - *                      in the array, the higher priority.
> - * @page_programs:	page program capabilities ordered by priority: the
> - *                      higher index in the array, the higher priority.
> - * @erase_map:		the erase map parsed from the SFDP Sector Map Parameter
> - *                      Table.
> - * @quad_enable:	enables SPI NOR quad mode.
> - * @set_4byte:		puts the SPI NOR in 4 byte addressing mode.
> - * @convert_addr:	converts an absolute address into something the flash
> - *                      will understand. Particularly useful when pagesize is
> - *                      not a power-of-2.
> - * @setup:              configures the SPI NOR memory. Useful for SPI NOR
> - *                      flashes that have peculiarities to the SPI NOR standard
> - *                      e.g. different opcodes, specific address calculation,
> - *                      page size, etc.
> - * @locking_ops:	SPI NOR locking methods.
> - */
> -struct spi_nor_flash_parameter {
> -	u64				size;
> -	u32				page_size;
> -
> -	struct spi_nor_hwcaps		hwcaps;
> -	struct spi_nor_read_command	reads[SNOR_CMD_READ_MAX];
> -	struct spi_nor_pp_command	page_programs[SNOR_CMD_PP_MAX];
>  
> -	struct spi_nor_erase_map        erase_map;
> -
> -	int (*quad_enable)(struct spi_nor *nor);
> -	int (*set_4byte)(struct spi_nor *nor, bool enable);
> -	u32 (*convert_addr)(struct spi_nor *nor, u32 addr);
> -	int (*setup)(struct spi_nor *nor, const struct spi_nor_hwcaps *hwcaps);
> -
> -	const struct spi_nor_locking_ops *locking_ops;
> -};
> -
> -/**
> - * struct flash_info - Forward declaration of a structure used internally by
> - *		       spi_nor_scan()
> +/*
> + * Forward declarations that are used internally by the core and manufacturer
> + * drivers.
>   */
>  struct flash_info;
> -
> -/**
> - * struct spi_nor_manufacturer - Forward declaration of a structure used
> - * internally by the core and manufacturer drivers.
> - */
>  struct spi_nor_manufacturer;
> +struct spi_nor_flash_parameter;
>  
>  /**
>   * struct spi_nor - Structure for defining a the SPI NOR layer
> @@ -613,7 +395,7 @@ struct spi_nor {
>  
>  	const struct spi_nor_controller_ops *controller_ops;
>  
> -	struct spi_nor_flash_parameter params;
> +	struct spi_nor_flash_parameter *params;
>  
>  	struct {
>  		struct spi_mem_dirmap_desc *rdesc;
> @@ -623,35 +405,6 @@ struct spi_nor {
>  	void *priv;
>  };
>  
> -static u64 __maybe_unused
> -spi_nor_region_is_last(const struct spi_nor_erase_region *region)
> -{
> -	return region->offset & SNOR_LAST_REGION;
> -}
> -
> -static u64 __maybe_unused
> -spi_nor_region_end(const struct spi_nor_erase_region *region)
> -{
> -	return (region->offset & ~SNOR_ERASE_FLAGS_MASK) + region->size;
> -}
> -
> -static void __maybe_unused
> -spi_nor_region_mark_end(struct spi_nor_erase_region *region)
> -{
> -	region->offset |= SNOR_LAST_REGION;
> -}
> -
> -static void __maybe_unused
> -spi_nor_region_mark_overlay(struct spi_nor_erase_region *region)
> -{
> -	region->offset |= SNOR_OVERLAID_REGION;
> -}
> -
> -static bool __maybe_unused spi_nor_has_uniform_erase(const struct spi_nor *nor)
> -{
> -	return !!nor->params.erase_map.uniform_erase_type;
> -}
> -
>  static inline void spi_nor_set_flash_node(struct spi_nor *nor,
>  					  struct device_node *np)
>  {
> 

-- 
Regards
Vignesh

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

* Re: [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h
  2020-03-13  8:13   ` Vignesh Raghavendra
@ 2020-03-13  8:27     ` Tudor.Ambarus
  0 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-13  8:27 UTC (permalink / raw)
  To: vigneshr
  Cc: bbrezillon, linux-mtd, miquel.raynal, richard, joel, andrew,
	Nicolas.Ferre, alexandre.belloni, Ludovic.Desroches,
	matthias.bgg, vz, michal.simek, ludovic.barre, john.garry, tglx,
	nishkadg.linux, michael, dinguyen, thor.thayer, swboyd,
	opensource, mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel

On Friday, March 13, 2020 10:13:17 AM EET Vignesh Raghavendra wrote:
> Should we drop SNOR_MFR_* macros as well or do you see a neeed for them?

Good catch. Cross-manufacturer code is unlikely and discouraged, we should get 
rid of them.

Cheers,
ta


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

* Re: [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name
  2020-03-13  6:04   ` Vignesh Raghavendra
@ 2020-03-13  9:30     ` Boris Brezillon
  2020-03-13 14:30       ` Tudor.Ambarus
  0 siblings, 1 reply; 39+ messages in thread
From: Boris Brezillon @ 2020-03-13  9:30 UTC (permalink / raw)
  To: Vignesh Raghavendra
  Cc: Tudor.Ambarus, bbrezillon, linux-mtd, miquel.raynal, richard,
	joel, andrew, Nicolas.Ferre, alexandre.belloni,
	Ludovic.Desroches, matthias.bgg, vz, michal.simek, ludovic.barre,
	john.garry, tglx, nishkadg.linux, michael, dinguyen, thor.thayer,
	swboyd, opensource, mika.westerberg, kstewart, allison, jethro,
	info, alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel

On Fri, 13 Mar 2020 11:34:55 +0530
Vignesh Raghavendra <vigneshr@ti.com> wrote:

> On 02/03/20 11:37 pm, Tudor.Ambarus@microchip.com wrote:
> > From: Boris Brezillon <bbrezillon@kernel.org>
> > 
> > Replace the manufacturer prefix by something describing more precisely
> > what those functions do.
> > 
> > Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> > [tudor.ambarus@microchip.com: prepend spi_nor_ to all modified methods.]
> > Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> > ---
> >  drivers/mtd/spi-nor/spi-nor.c | 88 ++++++++++++++++++-----------------
> >  1 file changed, 45 insertions(+), 43 deletions(-)
> > 
> > diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
> > index caf0c109cca0..b15e262765e1 100644
> > --- a/drivers/mtd/spi-nor/spi-nor.c
> > +++ b/drivers/mtd/spi-nor/spi-nor.c
> > @@ -568,14 +568,15 @@ static int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
> >  }
> >  
> >  /**
> > - * macronix_set_4byte() - Set 4-byte address mode for Macronix flashes.
> > + * spi_nor_en4_ex4_set_4byte() - Enter/Exit 4-byte mode for Macronix like
> > + * flashes.
> >   * @nor:	pointer to 'struct spi_nor'.
> >   * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
> >   *		address mode.
> >   *
> >   * Return: 0 on success, -errno otherwise.
> >   */
> > -static int macronix_set_4byte(struct spi_nor *nor, bool enable)
> > +static int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable)  
> 
> 
> Sounds a bit weird, how about simplifying this to:
> 
> 	spi_nor_set_4byte_addr_mode()
> 
> Or if you want to be specific:
> 
> 	spi_nor_en_ex_4byte_addr_mode()

You're right. Maybe we can simplify things by having a single function
that does optional steps based on new flags

SPI_NOR_EN_EX_4B_NEEDS_WEN
SPI_NOR_CLEAR_EAR_ON_4B_EXIT

This should probably be done in a separate patch though, so ack on the
spi_nor_en_ex_4byte_addr_mode() rename, assuming we also change the
bool argument name to enter.

> 
> >  {
> >  	int ret;
> >  
> > @@ -604,14 +605,15 @@ static int macronix_set_4byte(struct spi_nor *nor, bool enable)
> >  }
> >  
> >  /**
> > - * st_micron_set_4byte() - Set 4-byte address mode for ST and Micron flashes.
> > + * spi_nor_en4_ex4_wen_set_4byte() - Set 4-byte address mode for ST and Micron
> > + * flashes.
> >   * @nor:	pointer to 'struct spi_nor'.
> >   * @enable:	true to enter the 4-byte address mode, false to exit the 4-byte
> >   *		address mode.
> >   *
> >   * Return: 0 on success, -errno otherwise.
> >   */
> > -static int st_micron_set_4byte(struct spi_nor *nor, bool enable)
> > +static int spi_nor_en4_ex4_wen_set_4byte(struct spi_nor *nor, bool enable)  
> 
> 
> Unrelated to this patch itself, but can we just have one set_4byte
> variant that uses WREN and drop the other one?

Hm, not sure that's a good idea to insert WEN instructions for
everyone, sounds like a recipe for regressions.

> I expect sending WREN should be harmless even for cmds that don't expect
> one.

In theory yes, but you know flash chips are capricious, so let's not
take the risk of breaking things :-).

> 
> Rest looks good to me.
> 
> Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>
> 


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

* Re: [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name
  2020-03-13  9:30     ` Boris Brezillon
@ 2020-03-13 14:30       ` Tudor.Ambarus
  2020-03-13 15:50         ` Tudor.Ambarus
  0 siblings, 1 reply; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-13 14:30 UTC (permalink / raw)
  To: boris.brezillon
  Cc: vigneshr, bbrezillon, linux-mtd, miquel.raynal, richard, joel,
	andrew, Nicolas.Ferre, alexandre.belloni, Ludovic.Desroches,
	matthias.bgg, vz, michal.simek, ludovic.barre, john.garry, tglx,
	nishkadg.linux, michael, dinguyen, thor.thayer, swboyd,
	opensource, mika.westerberg, kstewart, allison, jethro, info,
	alexander.sverdlin, rfontana, linux-kernel, linux-mediatek,
	linux-aspeed, linux-arm-kernel

On Friday, March 13, 2020 11:30:07 AM EET Boris Brezillon wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the
> content is safe
> 
> On Fri, 13 Mar 2020 11:34:55 +0530
> 
> Vignesh Raghavendra <vigneshr@ti.com> wrote:
> > On 02/03/20 11:37 pm, Tudor.Ambarus@microchip.com wrote:
> > > From: Boris Brezillon <bbrezillon@kernel.org>
> > > 
> > > Replace the manufacturer prefix by something describing more precisely
> > > what those functions do.
> > > 
> > > Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> > > [tudor.ambarus@microchip.com: prepend spi_nor_ to all modified methods.]
> > > Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> > > ---
> > > 
> > >  drivers/mtd/spi-nor/spi-nor.c | 88 ++++++++++++++++++-----------------
> > >  1 file changed, 45 insertions(+), 43 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/spi-nor/spi-nor.c
> > > b/drivers/mtd/spi-nor/spi-nor.c
> > > index caf0c109cca0..b15e262765e1 100644
> > > --- a/drivers/mtd/spi-nor/spi-nor.c
> > > +++ b/drivers/mtd/spi-nor/spi-nor.c
> > > @@ -568,14 +568,15 @@ static int spi_nor_read_cr(struct spi_nor *nor, u8
> > > *cr)> > 
> > >  }
> > >  
> > >  /**
> > > 
> > > - * macronix_set_4byte() - Set 4-byte address mode for Macronix flashes.
> > > + * spi_nor_en4_ex4_set_4byte() - Enter/Exit 4-byte mode for Macronix
> > > like
> > > + * flashes.
> > > 
> > >   * @nor:   pointer to 'struct spi_nor'.
> > >   * @enable:        true to enter the 4-byte address mode, false to exit
> > >   the 4-byte *         address mode.
> > >   *
> > >   * Return: 0 on success, -errno otherwise.
> > >   */
> > > 
> > > -static int macronix_set_4byte(struct spi_nor *nor, bool enable)
> > > +static int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool enable)
> > 
> > Sounds a bit weird, how about simplifying this to:
> >       spi_nor_set_4byte_addr_mode()
> > 
> > Or if you want to be specific:
> >       spi_nor_en_ex_4byte_addr_mode()
> 
> You're right. Maybe we can simplify things by having a single function
> that does optional steps based on new flags
> 
> SPI_NOR_EN_EX_4B_NEEDS_WEN
> SPI_NOR_CLEAR_EAR_ON_4B_EXIT
> 
> This should probably be done in a separate patch though, so ack on the
> spi_nor_en_ex_4byte_addr_mode() rename, assuming we also change the
> bool argument name to enter.

A single big function will be ugly to handle because of the 
spansion_set_4byte() -> it uses a different opcode.

I like the nor->params>set_4byte hook.

I think that spi_nor_en4_ex4_set_4byte() can be renamed to spi_nor_set_4byte() 
and be the only set_4byte() method exposed to manufacturers. 
spansion_set_4byte() will be static in core.c and the rest will be private in 
the manufacturer drivers.

Here's how the manufacturers enter and exit the 4 byte mode:
-> eon, gidadevice, issi, macronix, xmc use EN4B/EX4B
-> micron-st needs WEN -> private method as they are the only ones that 
require this
-> newer spansion have a 4BAM opcode (new, public command), older spansion 
flashes use BRWR (legacy in core.c, spansion_set_4byte())
-> winbond set_4byte method is hackish and may be reason for just a flash 
fixup hook -> private method

Let me know if you agree with this, so I can respin later today or tomorrow.

cut

> 
> > I expect sending WREN should be harmless even for cmds that don't expect
> > one.

The commands may be ok, but the flash can be corrupted. The WEL bit is NOT 
reset after the completion of the EN4B command on macronix flashes, so the 
gates are opened for some inadvertent commands that may corrupt the memory.

Cheers,
ta


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

* Re: [PATCH 02/23] mtd: spi-nor: Prepare core / manufacturer code split
  2020-03-13  6:08   ` Vignesh Raghavendra
@ 2020-03-13 14:41     ` Tudor.Ambarus
  0 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-13 14:41 UTC (permalink / raw)
  To: linux-mtd
  Cc: vigneshr, bbrezillon, kstewart, alexandre.belloni, linux-aspeed,
	thor.thayer, jethro, rfontana, miquel.raynal, opensource,
	richard, michal.simek, Ludovic.Desroches, joel, nishkadg.linux,
	john.garry, vz, alexander.sverdlin, matthias.bgg, tglx, swboyd,
	mika.westerberg, allison, linux-arm-kernel, andrew,
	Nicolas.Ferre, linux-kernel, dinguyen, michael, ludovic.barre,
	linux-mediatek, info

On Friday, March 13, 2020 8:08:44 AM EET Vignesh Raghavendra wrote:
> On 02/03/20 11:37 pm, Tudor.Ambarus@microchip.com wrote:
> > From: Boris Brezillon <bbrezillon@kernel.org>
> > 
> > Move all SPI NOR controller drivers to a controllers/ sub-directory
> > so that we only have SPI NOR related source files under
> > drivers/mtd/spi-nor/.
> > 
> > Rename spi-nor.c into core.c, we are about to split this file in multiple
> > source files (one per manufacturer, plus one for the SFDP parsing logic).
> > 
> > Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> > Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> 
> Reviewed-by: Vignesh Raghavendra <vigneshr@ti.com>
> 
> 
> But there are at least two drivers being moved from spi-nor to spi/
> which would conflict with this change.
> 

I'll merge the immutable tag provided by Mark and respin this series on top of 
it, there will be no conflicts.

Cheers,
ta


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

* Re: [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name
  2020-03-13 14:30       ` Tudor.Ambarus
@ 2020-03-13 15:50         ` Tudor.Ambarus
  0 siblings, 0 replies; 39+ messages in thread
From: Tudor.Ambarus @ 2020-03-13 15:50 UTC (permalink / raw)
  To: linux-mtd
  Cc: boris.brezillon, kstewart, alexandre.belloni, vigneshr,
	linux-aspeed, thor.thayer, jethro, rfontana, miquel.raynal,
	opensource, richard, allison, michal.simek, Ludovic.Desroches,
	joel, nishkadg.linux, john.garry, vz, alexander.sverdlin,
	matthias.bgg, tglx, swboyd, mika.westerberg, ludovic.barre,
	linux-arm-kernel, bbrezillon, andrew, Nicolas.Ferre,
	linux-kernel, dinguyen, michael, linux-mediatek, info

On Friday, March 13, 2020 4:30:48 PM EET Tudor.Ambarus@microchip.com wrote:
> > > > - * macronix_set_4byte() - Set 4-byte address mode for Macronix
> > > > flashes.
> > > > + * spi_nor_en4_ex4_set_4byte() - Enter/Exit 4-byte mode for Macronix
> > > > like
> > > > + * flashes.
> > > > 
> > > > * @nor:   pointer to 'struct spi_nor'.
> > > > * @enable:        true to enter the 4-byte address mode, false to exit
> > > > the 4-byte *         address mode.
> > > > *
> > > > * Return: 0 on success, -errno otherwise.
> > > > */
> > > > 
> > > > -static int macronix_set_4byte(struct spi_nor *nor, bool enable)
> > > > +static int spi_nor_en4_ex4_set_4byte(struct spi_nor *nor, bool
> > > > enable)
> > > 
> > > Sounds a bit weird, how about simplifying this to:
> > > spi_nor_set_4byte_addr_mode()
> > > 
> > > Or if you want to be specific:
> > > spi_nor_en_ex_4byte_addr_mode()
> > 
> > You're right. Maybe we can simplify things by having a single function
> > that does optional steps based on new flags
> > 
> > SPI_NOR_EN_EX_4B_NEEDS_WEN
> > SPI_NOR_CLEAR_EAR_ON_4B_EXIT
> > 
> > This should probably be done in a separate patch though, so ack on the
> > spi_nor_en_ex_4byte_addr_mode() rename, assuming we also change the
> > bool argument name to enter.
> 
> A single big function will be ugly to handle because of the
> spansion_set_4byte() -> it uses a different opcode.
> 
> I like the nor->params>set_4byte hook.
> 
> I think that spi_nor_en4_ex4_set_4byte() can be renamed to
> spi_nor_set_4byte() and be the only set_4byte() method exposed to
> manufacturers.
> spansion_set_4byte() will be static in core.c and the rest will be private
> in the manufacturer drivers.
> 
> Here's how the manufacturers enter and exit the 4 byte mode:
> -> eon, gidadevice, issi, macronix, xmc use EN4B/EX4B
> -> micron-st needs WEN -> private method as they are the only ones that
> require this
> -> newer spansion have a 4BAM opcode (new, public command), older spansion
> flashes use BRWR (legacy in core.c, spansion_set_4byte())
> -> winbond set_4byte method is hackish and may be reason for just a flash
> fixup hook -> private method

I'll drop the set_4byte changes from this patch. I'm adding a dedicated patch 
immediately after this, to implement what I said above.

Cheers,
ta



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

end of thread, other threads:[~2020-03-13 15:50 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-02 18:07 [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 01/23] mtd: spi-nor: Stop prefixing generic functions with a manufacturer name Tudor.Ambarus
2020-03-13  6:04   ` Vignesh Raghavendra
2020-03-13  9:30     ` Boris Brezillon
2020-03-13 14:30       ` Tudor.Ambarus
2020-03-13 15:50         ` Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 02/23] mtd: spi-nor: Prepare core / manufacturer code split Tudor.Ambarus
2020-03-13  6:08   ` Vignesh Raghavendra
2020-03-13 14:41     ` Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 03/23] mtd: spi-nor: Move SFDP logic out of the core Tudor.Ambarus
2020-03-07 14:50   ` Boris Brezillon
2020-03-02 18:07 ` [PATCH 04/23] mtd: spi-nor: Expose stuctures and functions to manufacturer drivers Tudor.Ambarus
2020-03-13  6:38   ` Vignesh Raghavendra
2020-03-02 18:07 ` [PATCH 05/23] mtd: spi-nor: Add the concept of SPI NOR manufacturer driver Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 07/23] mtd: spi-nor: Move Eon bits out of core.c Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 06/23] mtd: spi-nor: Move Atmel " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 08/23] mtd: spi-nor: Move ESMT " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 09/23] mtd: spi-nor: Move Everspin " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 10/23] mtd: spi-nor: Move Fujitsu " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 12/23] mtd: spi-nor: Move Intel " Tudor.Ambarus
2020-03-03 10:22   ` Mika Westerberg
2020-03-02 18:07 ` [PATCH 11/23] mtd: spi-nor: Move GigaDevice " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 13/23] mtd: spi-nor: Move ISSI " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 14/23] mtd: spi-nor: Move Macronix " Tudor.Ambarus
2020-03-04  7:20   ` chenxiang (M)
2020-03-02 18:07 ` [PATCH 16/23] mtd: spi-nor: Move Spansion " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 15/23] mtd: spi-nor: Move Micron/ST " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 18/23] mtd: spi-nor: Move Winbond " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 17/23] mtd: spi-nor: Move SST " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 19/23] mtd: spi-nor: Move Catalyst " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 21/23] mtd: spi-nor: Move XMC " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 20/23] mtd: spi-nor: Move Xilinx " Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 22/23] mtd: spi-nor: Get rid of the now empty spi_nor_ids[] table Tudor.Ambarus
2020-03-02 18:07 ` [PATCH 23/23] mtd: spi-nor: Trim what is exposed in spi-nor.h Tudor.Ambarus
2020-03-07 14:49   ` Boris Brezillon
2020-03-13  8:13   ` Vignesh Raghavendra
2020-03-13  8:27     ` Tudor.Ambarus
2020-03-03  7:15 ` [PATCH 00/23] mtd: spi-nor: Move manufacturer/SFDP code out of the core Joel Stanley
2020-03-03  7:28   ` Tudor.Ambarus

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