All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 0/9] mtd: spi-nor: Rework Octal DTR methods
@ 2022-04-11  9:10 ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

v3:
- queue patch: "mtd: spi-nor: Introduce templates for SPI NOR operations"
from
https://lore.kernel.org/lkml/20220304093011.198173-1-tudor.ambarus@microchip.com/
The dependancy chain between patches was too long and hard to follow.

- Rework patch "mtd: spi-nor: core: Use auto-detection only once"
according to Pratyush's and Michael's suggestions
- Remove dev_dbg messge from spi_nor_read_id() method and let the callers
use their own message (detection, octal dtr enable/disable)
- detailed version changes in each patch
 
v2:
- Fix bug on octal dtr disable, s/nor->reg_proto/SNOR_PROTO_1_1_1,
because after disable the nor->proto is not yet updated
- update function/macros names to comply with Michael's rename series.

Tudor Ambarus (9):
  mtd: spi-nor: Rename method, s/spi_nor_match_id/spi_nor_match_name
  mtd: spi-nor: Introduce spi_nor_match_id()
  mtd: spi-nor: core: Use auto-detection only once
  mtd: spi-nor: core: Introduce method for RDID op
  mtd: spi-nor: manufacturers: Use spi_nor_read_id() core method
  mtd: spi-nor: core: Add helpers to read/write any register
  mtd: spi-nor: micron-st: Rework spi_nor_micron_octal_dtr_enable()
  mtd: spi-nor: spansion: Rework spi_nor_cypress_octal_dtr_enable()
  mtd: spi-nor: Introduce templates for SPI NOR operations

 drivers/mtd/spi-nor/core.c      | 249 ++++++++++++++++----------------
 drivers/mtd/spi-nor/core.h      | 115 +++++++++++++++
 drivers/mtd/spi-nor/micron-st.c | 142 +++++++++---------
 drivers/mtd/spi-nor/spansion.c  | 161 +++++++++++----------
 drivers/mtd/spi-nor/xilinx.c    |  12 +-
 5 files changed, 405 insertions(+), 274 deletions(-)

-- 
2.25.1


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

* [PATCH v3 0/9] mtd: spi-nor: Rework Octal DTR methods
@ 2022-04-11  9:10 ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

v3:
- queue patch: "mtd: spi-nor: Introduce templates for SPI NOR operations"
from
https://lore.kernel.org/lkml/20220304093011.198173-1-tudor.ambarus@microchip.com/
The dependancy chain between patches was too long and hard to follow.

- Rework patch "mtd: spi-nor: core: Use auto-detection only once"
according to Pratyush's and Michael's suggestions
- Remove dev_dbg messge from spi_nor_read_id() method and let the callers
use their own message (detection, octal dtr enable/disable)
- detailed version changes in each patch
 
v2:
- Fix bug on octal dtr disable, s/nor->reg_proto/SNOR_PROTO_1_1_1,
because after disable the nor->proto is not yet updated
- update function/macros names to comply with Michael's rename series.

Tudor Ambarus (9):
  mtd: spi-nor: Rename method, s/spi_nor_match_id/spi_nor_match_name
  mtd: spi-nor: Introduce spi_nor_match_id()
  mtd: spi-nor: core: Use auto-detection only once
  mtd: spi-nor: core: Introduce method for RDID op
  mtd: spi-nor: manufacturers: Use spi_nor_read_id() core method
  mtd: spi-nor: core: Add helpers to read/write any register
  mtd: spi-nor: micron-st: Rework spi_nor_micron_octal_dtr_enable()
  mtd: spi-nor: spansion: Rework spi_nor_cypress_octal_dtr_enable()
  mtd: spi-nor: Introduce templates for SPI NOR operations

 drivers/mtd/spi-nor/core.c      | 249 ++++++++++++++++----------------
 drivers/mtd/spi-nor/core.h      | 115 +++++++++++++++
 drivers/mtd/spi-nor/micron-st.c | 142 +++++++++---------
 drivers/mtd/spi-nor/spansion.c  | 161 +++++++++++----------
 drivers/mtd/spi-nor/xilinx.c    |  12 +-
 5 files changed, 405 insertions(+), 274 deletions(-)

-- 
2.25.1


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

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

* [PATCH v3 1/9] mtd: spi-nor: Rename method, s/spi_nor_match_id/spi_nor_match_name
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

The method is matching a flash_info entry by searching by name. Rename
the method for better clarity.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
Reviewed-by: Michael Walle <michael@walle.cc>
---
v3: collect R-bs

 drivers/mtd/spi-nor/core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index b4f141ad9c9c..214d3a1ac6b0 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2876,8 +2876,8 @@ void spi_nor_restore(struct spi_nor *nor)
 }
 EXPORT_SYMBOL_GPL(spi_nor_restore);
 
-static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
-						 const char *name)
+static const struct flash_info *spi_nor_match_name(struct spi_nor *nor,
+						   const char *name)
 {
 	unsigned int i, j;
 
@@ -2899,7 +2899,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(nor, name);
+		info = spi_nor_match_name(nor, name);
 	/* Try to auto-detect if chip name wasn't specified or not found */
 	if (!info)
 		info = spi_nor_read_id(nor);
-- 
2.25.1


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

* [PATCH v3 1/9] mtd: spi-nor: Rename method, s/spi_nor_match_id/spi_nor_match_name
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

The method is matching a flash_info entry by searching by name. Rename
the method for better clarity.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
Reviewed-by: Michael Walle <michael@walle.cc>
---
v3: collect R-bs

 drivers/mtd/spi-nor/core.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index b4f141ad9c9c..214d3a1ac6b0 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2876,8 +2876,8 @@ void spi_nor_restore(struct spi_nor *nor)
 }
 EXPORT_SYMBOL_GPL(spi_nor_restore);
 
-static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
-						 const char *name)
+static const struct flash_info *spi_nor_match_name(struct spi_nor *nor,
+						   const char *name)
 {
 	unsigned int i, j;
 
@@ -2899,7 +2899,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(nor, name);
+		info = spi_nor_match_name(nor, name);
 	/* Try to auto-detect if chip name wasn't specified or not found */
 	if (!info)
 		info = spi_nor_read_id(nor);
-- 
2.25.1


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

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

* [PATCH v3 2/9] mtd: spi-nor: Introduce spi_nor_match_id()
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Similar to spi_nor_match_name() extend the search of flash_info through
all the manufacturers, this time doing the match by ID. There's no reason
to limit the search per manufacturer yet, do it globally, search the flash
in all the parts of all manufacturers in a single method.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
Reviewed-by: Michael Walle <michael@walle.cc>
---
v3: collect R-bs

 drivers/mtd/spi-nor/core.c | 40 ++++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 214d3a1ac6b0..b9cc8bbf1f62 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1629,16 +1629,21 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_xmc,
 };
 
-static const struct flash_info *
-spi_nor_search_part_by_id(const struct flash_info *parts, unsigned int nparts,
-			  const u8 *id)
+static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
+						 const u8 *id)
 {
-	unsigned int i;
+	const struct flash_info *part;
+	unsigned int i, j;
 
-	for (i = 0; i < nparts; i++) {
-		if (parts[i].id_len &&
-		    !memcmp(parts[i].id, id, parts[i].id_len))
-			return &parts[i];
+	for (i = 0; i < ARRAY_SIZE(manufacturers); i++) {
+		for (j = 0; j < manufacturers[i]->nparts; j++) {
+			part = &manufacturers[i]->parts[j];
+			if (part->id_len &&
+			    !memcmp(part->id, id, part->id_len)) {
+				nor->manufacturer = manufacturers[i];
+				return part;
+			}
+		}
 	}
 
 	return NULL;
@@ -1648,7 +1653,6 @@ 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;
 
 	if (nor->spimem) {
@@ -1668,19 +1672,13 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
 		return ERR_PTR(ret);
 	}
 
-	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_match_id(nor, id);
+	if (!info) {
+		dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
+			SPI_NOR_MAX_ID_LEN, id);
+		return ERR_PTR(-ENODEV);
 	}
-
-	dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
-		SPI_NOR_MAX_ID_LEN, id);
-	return ERR_PTR(-ENODEV);
+	return info;
 }
 
 static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
-- 
2.25.1


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

* [PATCH v3 2/9] mtd: spi-nor: Introduce spi_nor_match_id()
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Similar to spi_nor_match_name() extend the search of flash_info through
all the manufacturers, this time doing the match by ID. There's no reason
to limit the search per manufacturer yet, do it globally, search the flash
in all the parts of all manufacturers in a single method.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
Reviewed-by: Michael Walle <michael@walle.cc>
---
v3: collect R-bs

 drivers/mtd/spi-nor/core.c | 40 ++++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 214d3a1ac6b0..b9cc8bbf1f62 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -1629,16 +1629,21 @@ static const struct spi_nor_manufacturer *manufacturers[] = {
 	&spi_nor_xmc,
 };
 
-static const struct flash_info *
-spi_nor_search_part_by_id(const struct flash_info *parts, unsigned int nparts,
-			  const u8 *id)
+static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
+						 const u8 *id)
 {
-	unsigned int i;
+	const struct flash_info *part;
+	unsigned int i, j;
 
-	for (i = 0; i < nparts; i++) {
-		if (parts[i].id_len &&
-		    !memcmp(parts[i].id, id, parts[i].id_len))
-			return &parts[i];
+	for (i = 0; i < ARRAY_SIZE(manufacturers); i++) {
+		for (j = 0; j < manufacturers[i]->nparts; j++) {
+			part = &manufacturers[i]->parts[j];
+			if (part->id_len &&
+			    !memcmp(part->id, id, part->id_len)) {
+				nor->manufacturer = manufacturers[i];
+				return part;
+			}
+		}
 	}
 
 	return NULL;
@@ -1648,7 +1653,6 @@ 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;
 
 	if (nor->spimem) {
@@ -1668,19 +1672,13 @@ static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
 		return ERR_PTR(ret);
 	}
 
-	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_match_id(nor, id);
+	if (!info) {
+		dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
+			SPI_NOR_MAX_ID_LEN, id);
+		return ERR_PTR(-ENODEV);
 	}
-
-	dev_err(nor->dev, "unrecognized JEDEC id bytes: %*ph\n",
-		SPI_NOR_MAX_ID_LEN, id);
-	return ERR_PTR(-ENODEV);
+	return info;
 }
 
 static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
-- 
2.25.1


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

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

* [PATCH v3 3/9] mtd: spi-nor: core: Use auto-detection only once
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

In case spi_nor_match_name() returned NULL, the auto detection was
issued twice. There's no reason to try to detect the same chip twice,
do the auto detection only once.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
v3:                                                                             
- caller of spi_nor_get_flash_info now handles NULL and translates it to        
ENOENT.

 drivers/mtd/spi-nor/core.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index b9cc8bbf1f62..b55d922d46dd 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2896,13 +2896,14 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
 {
 	const struct flash_info *info = NULL;
 
-	if (name)
+	if (name) {
 		info = spi_nor_match_name(nor, name);
+		if (IS_ERR(info))
+			return info;
+	}
 	/* Try to auto-detect if chip name wasn't specified or not found */
 	if (!info)
-		info = spi_nor_read_id(nor);
-	if (IS_ERR_OR_NULL(info))
-		return ERR_PTR(-ENOENT);
+		return spi_nor_read_id(nor);
 
 	/*
 	 * If caller has specified name of flash model that can normally be
@@ -2994,7 +2995,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 		return -ENOMEM;
 
 	info = spi_nor_get_flash_info(nor, name);
-	if (IS_ERR(info))
+	if (!info)
+		return -ENOENT;
+	else if (IS_ERR(info))
 		return PTR_ERR(info);
 
 	nor->info = info;
-- 
2.25.1


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

* [PATCH v3 3/9] mtd: spi-nor: core: Use auto-detection only once
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

In case spi_nor_match_name() returned NULL, the auto detection was
issued twice. There's no reason to try to detect the same chip twice,
do the auto detection only once.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
v3:                                                                             
- caller of spi_nor_get_flash_info now handles NULL and translates it to        
ENOENT.

 drivers/mtd/spi-nor/core.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index b9cc8bbf1f62..b55d922d46dd 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -2896,13 +2896,14 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
 {
 	const struct flash_info *info = NULL;
 
-	if (name)
+	if (name) {
 		info = spi_nor_match_name(nor, name);
+		if (IS_ERR(info))
+			return info;
+	}
 	/* Try to auto-detect if chip name wasn't specified or not found */
 	if (!info)
-		info = spi_nor_read_id(nor);
-	if (IS_ERR_OR_NULL(info))
-		return ERR_PTR(-ENOENT);
+		return spi_nor_read_id(nor);
 
 	/*
 	 * If caller has specified name of flash model that can normally be
@@ -2994,7 +2995,9 @@ int spi_nor_scan(struct spi_nor *nor, const char *name,
 		return -ENOMEM;
 
 	info = spi_nor_get_flash_info(nor, name);
-	if (IS_ERR(info))
+	if (!info)
+		return -ENOENT;
+	else if (IS_ERR(info))
 		return PTR_ERR(info);
 
 	nor->info = info;
-- 
2.25.1


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

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

* [PATCH v3 4/9] mtd: spi-nor: core: Introduce method for RDID op
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

RDID is used in the core to auto detect the flash, but also by some
manufacturer drivers that contain flashes that support Octal DTR mode,
so that they can read the flash ID after the switch to Octal DTR was made
to test if the switch was successful. Introduce a core method for RDID op
to avoid code duplication.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
v3: s/reg_proto/proto

 drivers/mtd/spi-nor/core.c | 50 ++++++++++++++++++++++++++------------
 drivers/mtd/spi-nor/core.h |  9 +++++++
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index b55d922d46dd..6165dc7bfd17 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -369,6 +369,37 @@ int spi_nor_write_disable(struct spi_nor *nor)
 	return ret;
 }
 
+/**
+ * spi_nor_read_id() - Read the JEDEC ID.
+ * @nor:	pointer to 'struct spi_nor'.
+ * @naddr:	number of address bytes to send. Can be zero if the operation
+ *		does not need to send an address.
+ * @ndummy:	number of dummy bytes to send after an opcode or address. Can
+ *		be zero if the operation does not require dummy bytes.
+ * @id:		pointer to a DMA-able buffer where the value of the JEDEC ID
+ *		will be written.
+ * @proto:	the SPI protocol for register operation.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
+		    enum spi_nor_protocol proto)
+{
+	int ret;
+
+	if (nor->spimem) {
+		struct spi_mem_op op =
+			SPI_NOR_READID_OP(naddr, ndummy, id, SPI_NOR_MAX_ID_LEN);
+
+		spi_nor_spimem_setup_op(nor, &op, proto);
+		ret = spi_mem_exec_op(nor->spimem, &op);
+	} else {
+		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
+						    SPI_NOR_MAX_ID_LEN);
+	}
+	return ret;
+}
+
 /**
  * spi_nor_read_sr() - Read the Status Register.
  * @nor:	pointer to 'struct spi_nor'.
@@ -1649,24 +1680,13 @@ static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
 	return NULL;
 }
 
-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
+static const struct flash_info *spi_nor_detect(struct spi_nor *nor)
 {
 	const struct flash_info *info;
 	u8 *id = nor->bouncebuf;
 	int ret;
 
-	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(SPI_NOR_MAX_ID_LEN, id, 1));
-
-		ret = spi_mem_exec_op(nor->spimem, &op);
-	} else {
-		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
-						    SPI_NOR_MAX_ID_LEN);
-	}
+	ret = spi_nor_read_id(nor, 0, 0, id, nor->reg_proto);
 	if (ret) {
 		dev_dbg(nor->dev, "error %d reading JEDEC ID\n", ret);
 		return ERR_PTR(ret);
@@ -2903,7 +2923,7 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
 	}
 	/* Try to auto-detect if chip name wasn't specified or not found */
 	if (!info)
-		return spi_nor_read_id(nor);
+		return spi_nor_detect(nor);
 
 	/*
 	 * If caller has specified name of flash model that can normally be
@@ -2912,7 +2932,7 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
 	if (name && info->id_len) {
 		const struct flash_info *jinfo;
 
-		jinfo = spi_nor_read_id(nor);
+		jinfo = spi_nor_detect(nor);
 		if (IS_ERR(jinfo)) {
 			return jinfo;
 		} else if (jinfo != info) {
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index b7fd760e3b47..f952061d5c24 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -11,6 +11,13 @@
 
 #define SPI_NOR_MAX_ID_LEN	6
 
+/* Standard SPI NOR flash operations. */
+#define SPI_NOR_READID_OP(naddr, ndummy, buf, len)			\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 0),			\
+		   SPI_MEM_OP_ADDR(naddr, 0, 0),			\
+		   SPI_MEM_OP_DUMMY(ndummy, 0),				\
+		   SPI_MEM_OP_DATA_IN(len, buf, 0))
+
 enum spi_nor_option_flags {
 	SNOR_F_HAS_SR_TB	= BIT(0),
 	SNOR_F_NO_OP_CHIP_ERASE	= BIT(1),
@@ -534,6 +541,8 @@ 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_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
+		    enum spi_nor_protocol reg_proto);
 int spi_nor_read_sr(struct spi_nor *nor, u8 *sr);
 int spi_nor_sr_ready(struct spi_nor *nor);
 int spi_nor_read_cr(struct spi_nor *nor, u8 *cr);
-- 
2.25.1


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

* [PATCH v3 4/9] mtd: spi-nor: core: Introduce method for RDID op
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

RDID is used in the core to auto detect the flash, but also by some
manufacturer drivers that contain flashes that support Octal DTR mode,
so that they can read the flash ID after the switch to Octal DTR was made
to test if the switch was successful. Introduce a core method for RDID op
to avoid code duplication.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
v3: s/reg_proto/proto

 drivers/mtd/spi-nor/core.c | 50 ++++++++++++++++++++++++++------------
 drivers/mtd/spi-nor/core.h |  9 +++++++
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index b55d922d46dd..6165dc7bfd17 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -369,6 +369,37 @@ int spi_nor_write_disable(struct spi_nor *nor)
 	return ret;
 }
 
+/**
+ * spi_nor_read_id() - Read the JEDEC ID.
+ * @nor:	pointer to 'struct spi_nor'.
+ * @naddr:	number of address bytes to send. Can be zero if the operation
+ *		does not need to send an address.
+ * @ndummy:	number of dummy bytes to send after an opcode or address. Can
+ *		be zero if the operation does not require dummy bytes.
+ * @id:		pointer to a DMA-able buffer where the value of the JEDEC ID
+ *		will be written.
+ * @proto:	the SPI protocol for register operation.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int spi_nor_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
+		    enum spi_nor_protocol proto)
+{
+	int ret;
+
+	if (nor->spimem) {
+		struct spi_mem_op op =
+			SPI_NOR_READID_OP(naddr, ndummy, id, SPI_NOR_MAX_ID_LEN);
+
+		spi_nor_spimem_setup_op(nor, &op, proto);
+		ret = spi_mem_exec_op(nor->spimem, &op);
+	} else {
+		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
+						    SPI_NOR_MAX_ID_LEN);
+	}
+	return ret;
+}
+
 /**
  * spi_nor_read_sr() - Read the Status Register.
  * @nor:	pointer to 'struct spi_nor'.
@@ -1649,24 +1680,13 @@ static const struct flash_info *spi_nor_match_id(struct spi_nor *nor,
 	return NULL;
 }
 
-static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
+static const struct flash_info *spi_nor_detect(struct spi_nor *nor)
 {
 	const struct flash_info *info;
 	u8 *id = nor->bouncebuf;
 	int ret;
 
-	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(SPI_NOR_MAX_ID_LEN, id, 1));
-
-		ret = spi_mem_exec_op(nor->spimem, &op);
-	} else {
-		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
-						    SPI_NOR_MAX_ID_LEN);
-	}
+	ret = spi_nor_read_id(nor, 0, 0, id, nor->reg_proto);
 	if (ret) {
 		dev_dbg(nor->dev, "error %d reading JEDEC ID\n", ret);
 		return ERR_PTR(ret);
@@ -2903,7 +2923,7 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
 	}
 	/* Try to auto-detect if chip name wasn't specified or not found */
 	if (!info)
-		return spi_nor_read_id(nor);
+		return spi_nor_detect(nor);
 
 	/*
 	 * If caller has specified name of flash model that can normally be
@@ -2912,7 +2932,7 @@ static const struct flash_info *spi_nor_get_flash_info(struct spi_nor *nor,
 	if (name && info->id_len) {
 		const struct flash_info *jinfo;
 
-		jinfo = spi_nor_read_id(nor);
+		jinfo = spi_nor_detect(nor);
 		if (IS_ERR(jinfo)) {
 			return jinfo;
 		} else if (jinfo != info) {
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index b7fd760e3b47..f952061d5c24 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -11,6 +11,13 @@
 
 #define SPI_NOR_MAX_ID_LEN	6
 
+/* Standard SPI NOR flash operations. */
+#define SPI_NOR_READID_OP(naddr, ndummy, buf, len)			\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 0),			\
+		   SPI_MEM_OP_ADDR(naddr, 0, 0),			\
+		   SPI_MEM_OP_DUMMY(ndummy, 0),				\
+		   SPI_MEM_OP_DATA_IN(len, buf, 0))
+
 enum spi_nor_option_flags {
 	SNOR_F_HAS_SR_TB	= BIT(0),
 	SNOR_F_NO_OP_CHIP_ERASE	= BIT(1),
@@ -534,6 +541,8 @@ 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_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
+		    enum spi_nor_protocol reg_proto);
 int spi_nor_read_sr(struct spi_nor *nor, u8 *sr);
 int spi_nor_sr_ready(struct spi_nor *nor);
 int spi_nor_read_cr(struct spi_nor *nor, u8 *cr);
-- 
2.25.1


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

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

* [PATCH v3 5/9] mtd: spi-nor: manufacturers: Use spi_nor_read_id() core method
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Use spi_nor_read_id() core method to avoid duplication of code. Now the ID
is read on the full SPI_NOR_MAX_ID_LEN instead of
round_up(nor->info->id_len, 2), but it doesn't harm to read more ID bytes,
so the change comes with no secondary effects. dev_dbg messages in case
spi_nor_read_id() fails, will be added in a further patch after we split
the octal DTR enable/disable methods.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
---
v3: collect R-b, update commit message

 drivers/mtd/spi-nor/micron-st.c | 13 +++----------
 drivers/mtd/spi-nor/spansion.c  | 13 +++----------
 2 files changed, 6 insertions(+), 20 deletions(-)

diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index 8a20475ce77a..41b87868ecf9 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -91,17 +91,10 @@ static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 		return ret;
 
 	/* Read flash ID to make sure the switch was successful. */
-	op = (struct spi_mem_op)
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
-			   SPI_MEM_OP_NO_ADDR,
-			   SPI_MEM_OP_DUMMY(enable ? 8 : 0, 1),
-			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
-					      buf, 1));
-
 	if (enable)
-		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
-
-	ret = spi_mem_exec_op(nor->spimem, &op);
+		ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
+	else
+		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
 	if (ret)
 		return ret;
 
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index f24e546e04a5..c5988312cc91 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -98,17 +98,10 @@ static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 		return ret;
 
 	/* Read flash ID to make sure the switch was successful. */
-	op = (struct spi_mem_op)
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
-			   SPI_MEM_OP_ADDR(enable ? 4 : 0, 0, 1),
-			   SPI_MEM_OP_DUMMY(enable ? 3 : 0, 1),
-			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
-					      buf, 1));
-
 	if (enable)
-		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
-
-	ret = spi_mem_exec_op(nor->spimem, &op);
+		ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
+	else
+		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
 	if (ret)
 		return ret;
 
-- 
2.25.1


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

* [PATCH v3 5/9] mtd: spi-nor: manufacturers: Use spi_nor_read_id() core method
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Use spi_nor_read_id() core method to avoid duplication of code. Now the ID
is read on the full SPI_NOR_MAX_ID_LEN instead of
round_up(nor->info->id_len, 2), but it doesn't harm to read more ID bytes,
so the change comes with no secondary effects. dev_dbg messages in case
spi_nor_read_id() fails, will be added in a further patch after we split
the octal DTR enable/disable methods.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
---
v3: collect R-b, update commit message

 drivers/mtd/spi-nor/micron-st.c | 13 +++----------
 drivers/mtd/spi-nor/spansion.c  | 13 +++----------
 2 files changed, 6 insertions(+), 20 deletions(-)

diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index 8a20475ce77a..41b87868ecf9 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -91,17 +91,10 @@ static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 		return ret;
 
 	/* Read flash ID to make sure the switch was successful. */
-	op = (struct spi_mem_op)
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
-			   SPI_MEM_OP_NO_ADDR,
-			   SPI_MEM_OP_DUMMY(enable ? 8 : 0, 1),
-			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
-					      buf, 1));
-
 	if (enable)
-		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
-
-	ret = spi_mem_exec_op(nor->spimem, &op);
+		ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
+	else
+		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
 	if (ret)
 		return ret;
 
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index f24e546e04a5..c5988312cc91 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -98,17 +98,10 @@ static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 		return ret;
 
 	/* Read flash ID to make sure the switch was successful. */
-	op = (struct spi_mem_op)
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
-			   SPI_MEM_OP_ADDR(enable ? 4 : 0, 0, 1),
-			   SPI_MEM_OP_DUMMY(enable ? 3 : 0, 1),
-			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
-					      buf, 1));
-
 	if (enable)
-		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
-
-	ret = spi_mem_exec_op(nor->spimem, &op);
+		ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
+	else
+		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
 	if (ret)
 		return ret;
 
-- 
2.25.1


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

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

* [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus, Takahiro Kuwano

There are manufacturers that use registers indexed by address. Some of
them support "read/write any register" opcodes. Provide core methods that
can be used by all manufacturers. SPI NOR controller ops are intentionally
not supported as we intend to move all the SPI NOR controller drivers
under the SPI subsystem.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
---
v3: no changes

 drivers/mtd/spi-nor/core.c | 41 ++++++++++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.h |  4 ++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 6165dc7bfd17..42794328d3b6 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
 	return nor->controller_ops->write(nor, to, len, buf);
 }
 
+/**
+ * spi_nor_read_reg() - read register to flash memory
+ * @nor:        pointer to 'struct spi_nor'.
+ * @op:		SPI memory operation. op->data.buf must be DMA-able.
+ * @proto:	SPI protocol to use for the register operation.
+ *
+ * Return: zero on success, -errno otherwise
+ */
+int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
+		     enum spi_nor_protocol proto)
+{
+	if (!nor->spimem)
+		return -EOPNOTSUPP;
+
+	spi_nor_spimem_setup_op(nor, op, proto);
+	return spi_nor_spimem_exec_op(nor, op);
+}
+
+/**
+ * spi_nor_write_reg() - write register to flash memory
+ * @nor:        pointer to 'struct spi_nor'
+ * @op:		SPI memory operation. op->data.buf must be DMA-able.
+ * @proto:	SPI protocol to use for the register operation.
+ *
+ * Return: zero on success, -errno otherwise
+ */
+int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
+		      enum spi_nor_protocol proto)
+{
+	int ret;
+
+	if (!nor->spimem)
+		return -EOPNOTSUPP;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+	spi_nor_spimem_setup_op(nor, op, proto);
+	return spi_nor_spimem_exec_op(nor, op);
+}
+
 /**
  * spi_nor_write_enable() - Set write enable latch with Write Enable command.
  * @nor:	pointer to 'struct spi_nor'.
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index f952061d5c24..7c704475946d 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -554,6 +554,10 @@ 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_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
+		     enum spi_nor_protocol proto);
+int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
+		      enum spi_nor_protocol proto);
 int spi_nor_erase_sector(struct spi_nor *nor, u32 addr);
 
 int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t len, u8 *buf);
-- 
2.25.1


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

* [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus, Takahiro Kuwano

There are manufacturers that use registers indexed by address. Some of
them support "read/write any register" opcodes. Provide core methods that
can be used by all manufacturers. SPI NOR controller ops are intentionally
not supported as we intend to move all the SPI NOR controller drivers
under the SPI subsystem.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
---
v3: no changes

 drivers/mtd/spi-nor/core.c | 41 ++++++++++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.h |  4 ++++
 2 files changed, 45 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 6165dc7bfd17..42794328d3b6 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
 	return nor->controller_ops->write(nor, to, len, buf);
 }
 
+/**
+ * spi_nor_read_reg() - read register to flash memory
+ * @nor:        pointer to 'struct spi_nor'.
+ * @op:		SPI memory operation. op->data.buf must be DMA-able.
+ * @proto:	SPI protocol to use for the register operation.
+ *
+ * Return: zero on success, -errno otherwise
+ */
+int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
+		     enum spi_nor_protocol proto)
+{
+	if (!nor->spimem)
+		return -EOPNOTSUPP;
+
+	spi_nor_spimem_setup_op(nor, op, proto);
+	return spi_nor_spimem_exec_op(nor, op);
+}
+
+/**
+ * spi_nor_write_reg() - write register to flash memory
+ * @nor:        pointer to 'struct spi_nor'
+ * @op:		SPI memory operation. op->data.buf must be DMA-able.
+ * @proto:	SPI protocol to use for the register operation.
+ *
+ * Return: zero on success, -errno otherwise
+ */
+int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
+		      enum spi_nor_protocol proto)
+{
+	int ret;
+
+	if (!nor->spimem)
+		return -EOPNOTSUPP;
+
+	ret = spi_nor_write_enable(nor);
+	if (ret)
+		return ret;
+	spi_nor_spimem_setup_op(nor, op, proto);
+	return spi_nor_spimem_exec_op(nor, op);
+}
+
 /**
  * spi_nor_write_enable() - Set write enable latch with Write Enable command.
  * @nor:	pointer to 'struct spi_nor'.
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index f952061d5c24..7c704475946d 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -554,6 +554,10 @@ 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_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
+		     enum spi_nor_protocol proto);
+int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
+		      enum spi_nor_protocol proto);
 int spi_nor_erase_sector(struct spi_nor *nor, u32 addr);
 
 int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t len, u8 *buf);
-- 
2.25.1


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

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

* [PATCH v3 7/9] mtd: spi-nor: micron-st: Rework spi_nor_micron_octal_dtr_enable()
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Introduce template operation to remove code duplication.
Split spi_nor_micron_octal_dtr_enable() in spi_nor_micron_octal_dtr_en()
and spi_nor_micron_octal_dtr_dis() as it no longer made sense to try to
keep everything alltogether: too many "if (enable)" throughout the code,
which made the code difficult to follow. Add dev_dbg messages in case
spi_nor_read_id() fails.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
---
v3: collect R-b, update commit message, add dev_dbg message in case             
spi_nor_read_id() fails.

 drivers/mtd/spi-nor/micron-st.c | 111 +++++++++++++++++---------------
 1 file changed, 60 insertions(+), 51 deletions(-)

diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index 41b87868ecf9..a447762c0d78 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -28,75 +28,78 @@
 #define FSR_P_ERR		BIT(4)	/* Program operation status */
 #define FSR_PT_ERR		BIT(1)	/* Protection error bit */
 
-static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+/* Micron ST SPI NOR flash operations. */
+#define MICRON_ST_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 0),		\
+		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
+
+static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
 	u8 *buf = nor->bouncebuf;
 	int ret;
 
-	if (enable) {
-		/* Use 20 dummy cycles for memory array reads. */
-		ret = spi_nor_write_enable(nor);
-		if (ret)
-			return ret;
-
-		*buf = 20;
-		op = (struct spi_mem_op)
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
-				   SPI_MEM_OP_ADDR(3, SPINOR_REG_MT_CFR1V, 1),
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, buf, 1));
-
-		ret = spi_mem_exec_op(nor->spimem, &op);
-		if (ret)
-			return ret;
-
-		ret = spi_nor_wait_till_ready(nor);
-		if (ret)
-			return ret;
-	}
+	/* Use 20 dummy cycles for memory array reads. */
+	*buf = 20;
+	op = (struct spi_mem_op)
+		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR1V, 1, buf);
+	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
+	if (ret)
+		return ret;
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret)
+		return ret;
 
-	ret = spi_nor_write_enable(nor);
+	buf[0] = SPINOR_MT_OCT_DTR;
+	op = (struct spi_mem_op)
+		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR0V, 1, buf);
+	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
 	if (ret)
 		return ret;
 
-	if (enable) {
-		buf[0] = SPINOR_MT_OCT_DTR;
-	} else {
-		/*
-		 * The register is 1-byte wide, but 1-byte transactions are not
-		 * allowed in 8D-8D-8D mode. The next register is the dummy
-		 * cycle configuration register. Since the transaction needs to
-		 * be at least 2 bytes wide, set the next register to its
-		 * default value. This also makes sense because the value was
-		 * changed when enabling 8D-8D-8D mode, it should be reset when
-		 * disabling.
-		 */
-		buf[0] = SPINOR_MT_EXSPI;
-		buf[1] = SPINOR_REG_MT_CFR1V_DEF;
+	/* Read flash ID to make sure the switch was successful. */
+	ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
+		return ret;
 	}
 
-	op = (struct spi_mem_op)
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
-			   SPI_MEM_OP_ADDR(enable ? 3 : 4,
-					   SPINOR_REG_MT_CFR0V, 1),
-			   SPI_MEM_OP_NO_DUMMY,
-			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
+	if (memcmp(buf, nor->info->id, nor->info->id_len))
+		return -EINVAL;
 
-	if (!enable)
-		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+	return 0;
+}
+
+static int micron_st_nor_octal_dtr_dis(struct spi_nor *nor)
+{
+	struct spi_mem_op op;
+	u8 *buf = nor->bouncebuf;
+	int ret;
 
-	ret = spi_mem_exec_op(nor->spimem, &op);
+	/*
+	 * The register is 1-byte wide, but 1-byte transactions are not allowed
+	 * in 8D-8D-8D mode. The next register is the dummy cycle configuration
+	 * register. Since the transaction needs to be at least 2 bytes wide,
+	 * set the next register to its default value. This also makes sense
+	 * because the value was changed when enabling 8D-8D-8D mode, it should
+	 * be reset when disabling.
+	 */
+	buf[0] = SPINOR_MT_EXSPI;
+	buf[1] = SPINOR_REG_MT_CFR1V_DEF;
+	op = (struct spi_mem_op)
+		MICRON_ST_NOR_WR_ANY_REG_OP(4, SPINOR_REG_MT_CFR0V, 2, buf);
+	ret = spi_nor_write_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
 	if (ret)
 		return ret;
 
 	/* Read flash ID to make sure the switch was successful. */
-	if (enable)
-		ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
-	else
-		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
-	if (ret)
+	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
 		return ret;
+	}
 
 	if (memcmp(buf, nor->info->id, nor->info->id_len))
 		return -EINVAL;
@@ -104,6 +107,12 @@ static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 	return 0;
 }
 
+static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+{
+	return enable ? micron_st_nor_octal_dtr_en(nor) :
+			micron_st_nor_octal_dtr_dis(nor);
+}
+
 static void mt35xu512aba_default_init(struct spi_nor *nor)
 {
 	nor->params->octal_dtr_enable = micron_st_nor_octal_dtr_enable;
-- 
2.25.1


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

* [PATCH v3 7/9] mtd: spi-nor: micron-st: Rework spi_nor_micron_octal_dtr_enable()
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Introduce template operation to remove code duplication.
Split spi_nor_micron_octal_dtr_enable() in spi_nor_micron_octal_dtr_en()
and spi_nor_micron_octal_dtr_dis() as it no longer made sense to try to
keep everything alltogether: too many "if (enable)" throughout the code,
which made the code difficult to follow. Add dev_dbg messages in case
spi_nor_read_id() fails.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
---
v3: collect R-b, update commit message, add dev_dbg message in case             
spi_nor_read_id() fails.

 drivers/mtd/spi-nor/micron-st.c | 111 +++++++++++++++++---------------
 1 file changed, 60 insertions(+), 51 deletions(-)

diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index 41b87868ecf9..a447762c0d78 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -28,75 +28,78 @@
 #define FSR_P_ERR		BIT(4)	/* Program operation status */
 #define FSR_PT_ERR		BIT(1)	/* Protection error bit */
 
-static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+/* Micron ST SPI NOR flash operations. */
+#define MICRON_ST_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 0),		\
+		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
+
+static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
 	u8 *buf = nor->bouncebuf;
 	int ret;
 
-	if (enable) {
-		/* Use 20 dummy cycles for memory array reads. */
-		ret = spi_nor_write_enable(nor);
-		if (ret)
-			return ret;
-
-		*buf = 20;
-		op = (struct spi_mem_op)
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
-				   SPI_MEM_OP_ADDR(3, SPINOR_REG_MT_CFR1V, 1),
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, buf, 1));
-
-		ret = spi_mem_exec_op(nor->spimem, &op);
-		if (ret)
-			return ret;
-
-		ret = spi_nor_wait_till_ready(nor);
-		if (ret)
-			return ret;
-	}
+	/* Use 20 dummy cycles for memory array reads. */
+	*buf = 20;
+	op = (struct spi_mem_op)
+		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR1V, 1, buf);
+	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
+	if (ret)
+		return ret;
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret)
+		return ret;
 
-	ret = spi_nor_write_enable(nor);
+	buf[0] = SPINOR_MT_OCT_DTR;
+	op = (struct spi_mem_op)
+		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR0V, 1, buf);
+	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
 	if (ret)
 		return ret;
 
-	if (enable) {
-		buf[0] = SPINOR_MT_OCT_DTR;
-	} else {
-		/*
-		 * The register is 1-byte wide, but 1-byte transactions are not
-		 * allowed in 8D-8D-8D mode. The next register is the dummy
-		 * cycle configuration register. Since the transaction needs to
-		 * be at least 2 bytes wide, set the next register to its
-		 * default value. This also makes sense because the value was
-		 * changed when enabling 8D-8D-8D mode, it should be reset when
-		 * disabling.
-		 */
-		buf[0] = SPINOR_MT_EXSPI;
-		buf[1] = SPINOR_REG_MT_CFR1V_DEF;
+	/* Read flash ID to make sure the switch was successful. */
+	ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
+		return ret;
 	}
 
-	op = (struct spi_mem_op)
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
-			   SPI_MEM_OP_ADDR(enable ? 3 : 4,
-					   SPINOR_REG_MT_CFR0V, 1),
-			   SPI_MEM_OP_NO_DUMMY,
-			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
+	if (memcmp(buf, nor->info->id, nor->info->id_len))
+		return -EINVAL;
 
-	if (!enable)
-		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+	return 0;
+}
+
+static int micron_st_nor_octal_dtr_dis(struct spi_nor *nor)
+{
+	struct spi_mem_op op;
+	u8 *buf = nor->bouncebuf;
+	int ret;
 
-	ret = spi_mem_exec_op(nor->spimem, &op);
+	/*
+	 * The register is 1-byte wide, but 1-byte transactions are not allowed
+	 * in 8D-8D-8D mode. The next register is the dummy cycle configuration
+	 * register. Since the transaction needs to be at least 2 bytes wide,
+	 * set the next register to its default value. This also makes sense
+	 * because the value was changed when enabling 8D-8D-8D mode, it should
+	 * be reset when disabling.
+	 */
+	buf[0] = SPINOR_MT_EXSPI;
+	buf[1] = SPINOR_REG_MT_CFR1V_DEF;
+	op = (struct spi_mem_op)
+		MICRON_ST_NOR_WR_ANY_REG_OP(4, SPINOR_REG_MT_CFR0V, 2, buf);
+	ret = spi_nor_write_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
 	if (ret)
 		return ret;
 
 	/* Read flash ID to make sure the switch was successful. */
-	if (enable)
-		ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
-	else
-		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
-	if (ret)
+	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
 		return ret;
+	}
 
 	if (memcmp(buf, nor->info->id, nor->info->id_len))
 		return -EINVAL;
@@ -104,6 +107,12 @@ static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 	return 0;
 }
 
+static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+{
+	return enable ? micron_st_nor_octal_dtr_en(nor) :
+			micron_st_nor_octal_dtr_dis(nor);
+}
+
 static void mt35xu512aba_default_init(struct spi_nor *nor)
 {
 	nor->params->octal_dtr_enable = micron_st_nor_octal_dtr_enable;
-- 
2.25.1


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

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

* [PATCH v3 8/9] mtd: spi-nor: spansion: Rework spi_nor_cypress_octal_dtr_enable()
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Introduce template operation to remove code duplication.
Split spi_nor_cypress_octal_dtr_enable() in
spi_nor_cypress_octal_dtr_ena() spi_nor_cypress_octal_dtr_dis() as it no
longer made sense to try to keep everything alltogether: too many
"if (enable)" throughout the code, which made the code difficult to read.
Add debug messages in case spi_nor_read_id() fails.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
---
v3: collect R-b, update commit message, add dev_dbg message in case             
spi_nor_read_id() fails.

 drivers/mtd/spi-nor/spansion.c | 128 ++++++++++++++++++---------------
 1 file changed, 69 insertions(+), 59 deletions(-)

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index c5988312cc91..35d8edb515a3 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -23,87 +23,81 @@
 #define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS	0
 #define SPINOR_OP_CYPRESS_RD_FAST		0xee
 
-/**
- * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
- * @nor:		pointer to a 'struct spi_nor'
- * @enable:              whether to enable or disable Octal DTR
- *
- * This also sets the memory access latency cycles to 24 to allow the flash to
- * run at up to 200MHz.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+/* Cypress SPI NOR flash operations. */
+#define CYPRESS_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 0),		\
+		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
+
+static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
 	u8 *buf = nor->bouncebuf;
 	int ret;
 
-	if (enable) {
-		/* Use 24 dummy cycles for memory array reads. */
-		ret = spi_nor_write_enable(nor);
-		if (ret)
-			return ret;
+	/* Use 24 dummy cycles for memory array reads. */
+	*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
+	op = (struct spi_mem_op)
+		CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR2V, 1, buf);
 
-		*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
-		op = (struct spi_mem_op)
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
-				   SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR2V,
-						   1),
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, buf, 1));
+	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
+	if (ret)
+		return ret;
 
-		ret = spi_mem_exec_op(nor->spimem, &op);
-		if (ret)
-			return ret;
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret)
+		return ret;
 
-		ret = spi_nor_wait_till_ready(nor);
-		if (ret)
-			return ret;
+	nor->read_dummy = 24;
 
-		nor->read_dummy = 24;
-	}
+	/* Set the octal and DTR enable bits. */
+	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
+	op = (struct spi_mem_op)
+		CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR5V, 1, buf);
 
-	/* Set/unset the octal and DTR enable bits. */
-	ret = spi_nor_write_enable(nor);
+	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
 	if (ret)
 		return ret;
 
-	if (enable) {
-		buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
-	} else {
-		/*
-		 * The register is 1-byte wide, but 1-byte transactions are not
-		 * allowed in 8D-8D-8D mode. Since there is no register at the
-		 * next location, just initialize the value to 0 and let the
-		 * transaction go on.
-		 */
-		buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
-		buf[1] = 0;
+	/* Read flash ID to make sure the switch was successful. */
+	ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
+		return ret;
 	}
 
-	op = (struct spi_mem_op)
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
-			   SPI_MEM_OP_ADDR(enable ? 3 : 4,
-					   SPINOR_REG_CYPRESS_CFR5V,
-					   1),
-			   SPI_MEM_OP_NO_DUMMY,
-			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
+	if (memcmp(buf, nor->info->id, nor->info->id_len))
+		return -EINVAL;
 
-	if (!enable)
-		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+	return 0;
+}
 
-	ret = spi_mem_exec_op(nor->spimem, &op);
+static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
+{
+	struct spi_mem_op op;
+	u8 *buf = nor->bouncebuf;
+	int ret;
+
+	/*
+	 * The register is 1-byte wide, but 1-byte transactions are not allowed
+	 * in 8D-8D-8D mode. Since there is no register at the next location,
+	 * just initialize the value to 0 and let the transaction go on.
+	 */
+	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
+	buf[1] = 0;
+	op = (struct spi_mem_op)
+		CYPRESS_NOR_WR_ANY_REG_OP(4, SPINOR_REG_CYPRESS_CFR5V, 2, buf);
+	ret = spi_nor_write_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
 	if (ret)
 		return ret;
 
 	/* Read flash ID to make sure the switch was successful. */
-	if (enable)
-		ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
-	else
-		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
-	if (ret)
+	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
 		return ret;
+	}
 
 	if (memcmp(buf, nor->info->id, nor->info->id_len))
 		return -EINVAL;
@@ -111,6 +105,22 @@ static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 	return 0;
 }
 
+/**
+ * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
+ * @nor:		pointer to a 'struct spi_nor'
+ * @enable:              whether to enable or disable Octal DTR
+ *
+ * This also sets the memory access latency cycles to 24 to allow the flash to
+ * run at up to 200MHz.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+{
+	return enable ? cypress_nor_octal_dtr_en(nor) :
+			cypress_nor_octal_dtr_dis(nor);
+}
+
 static void s28hs512t_default_init(struct spi_nor *nor)
 {
 	nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable;
-- 
2.25.1


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

* [PATCH v3 8/9] mtd: spi-nor: spansion: Rework spi_nor_cypress_octal_dtr_enable()
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Introduce template operation to remove code duplication.
Split spi_nor_cypress_octal_dtr_enable() in
spi_nor_cypress_octal_dtr_ena() spi_nor_cypress_octal_dtr_dis() as it no
longer made sense to try to keep everything alltogether: too many
"if (enable)" throughout the code, which made the code difficult to read.
Add debug messages in case spi_nor_read_id() fails.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
---
v3: collect R-b, update commit message, add dev_dbg message in case             
spi_nor_read_id() fails.

 drivers/mtd/spi-nor/spansion.c | 128 ++++++++++++++++++---------------
 1 file changed, 69 insertions(+), 59 deletions(-)

diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index c5988312cc91..35d8edb515a3 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -23,87 +23,81 @@
 #define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS	0
 #define SPINOR_OP_CYPRESS_RD_FAST		0xee
 
-/**
- * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
- * @nor:		pointer to a 'struct spi_nor'
- * @enable:              whether to enable or disable Octal DTR
- *
- * This also sets the memory access latency cycles to 24 to allow the flash to
- * run at up to 200MHz.
- *
- * Return: 0 on success, -errno otherwise.
- */
-static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+/* Cypress SPI NOR flash operations. */
+#define CYPRESS_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 0),		\
+		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
+
+static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
 	u8 *buf = nor->bouncebuf;
 	int ret;
 
-	if (enable) {
-		/* Use 24 dummy cycles for memory array reads. */
-		ret = spi_nor_write_enable(nor);
-		if (ret)
-			return ret;
+	/* Use 24 dummy cycles for memory array reads. */
+	*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
+	op = (struct spi_mem_op)
+		CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR2V, 1, buf);
 
-		*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
-		op = (struct spi_mem_op)
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
-				   SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR2V,
-						   1),
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, buf, 1));
+	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
+	if (ret)
+		return ret;
 
-		ret = spi_mem_exec_op(nor->spimem, &op);
-		if (ret)
-			return ret;
+	ret = spi_nor_wait_till_ready(nor);
+	if (ret)
+		return ret;
 
-		ret = spi_nor_wait_till_ready(nor);
-		if (ret)
-			return ret;
+	nor->read_dummy = 24;
 
-		nor->read_dummy = 24;
-	}
+	/* Set the octal and DTR enable bits. */
+	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
+	op = (struct spi_mem_op)
+		CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR5V, 1, buf);
 
-	/* Set/unset the octal and DTR enable bits. */
-	ret = spi_nor_write_enable(nor);
+	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
 	if (ret)
 		return ret;
 
-	if (enable) {
-		buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
-	} else {
-		/*
-		 * The register is 1-byte wide, but 1-byte transactions are not
-		 * allowed in 8D-8D-8D mode. Since there is no register at the
-		 * next location, just initialize the value to 0 and let the
-		 * transaction go on.
-		 */
-		buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
-		buf[1] = 0;
+	/* Read flash ID to make sure the switch was successful. */
+	ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling 8D-8D-8D mode\n", ret);
+		return ret;
 	}
 
-	op = (struct spi_mem_op)
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
-			   SPI_MEM_OP_ADDR(enable ? 3 : 4,
-					   SPINOR_REG_CYPRESS_CFR5V,
-					   1),
-			   SPI_MEM_OP_NO_DUMMY,
-			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
+	if (memcmp(buf, nor->info->id, nor->info->id_len))
+		return -EINVAL;
 
-	if (!enable)
-		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
+	return 0;
+}
 
-	ret = spi_mem_exec_op(nor->spimem, &op);
+static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
+{
+	struct spi_mem_op op;
+	u8 *buf = nor->bouncebuf;
+	int ret;
+
+	/*
+	 * The register is 1-byte wide, but 1-byte transactions are not allowed
+	 * in 8D-8D-8D mode. Since there is no register at the next location,
+	 * just initialize the value to 0 and let the transaction go on.
+	 */
+	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
+	buf[1] = 0;
+	op = (struct spi_mem_op)
+		CYPRESS_NOR_WR_ANY_REG_OP(4, SPINOR_REG_CYPRESS_CFR5V, 2, buf);
+	ret = spi_nor_write_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
 	if (ret)
 		return ret;
 
 	/* Read flash ID to make sure the switch was successful. */
-	if (enable)
-		ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
-	else
-		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
-	if (ret)
+	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
+	if (ret) {
+		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling 8D-8D-8D mode\n", ret);
 		return ret;
+	}
 
 	if (memcmp(buf, nor->info->id, nor->info->id_len))
 		return -EINVAL;
@@ -111,6 +105,22 @@ static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
 	return 0;
 }
 
+/**
+ * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress flashes.
+ * @nor:		pointer to a 'struct spi_nor'
+ * @enable:              whether to enable or disable Octal DTR
+ *
+ * This also sets the memory access latency cycles to 24 to allow the flash to
+ * run at up to 200MHz.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool enable)
+{
+	return enable ? cypress_nor_octal_dtr_en(nor) :
+			cypress_nor_octal_dtr_dis(nor);
+}
+
 static void s28hs512t_default_init(struct spi_nor *nor)
 {
 	nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable;
-- 
2.25.1


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

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

* [PATCH v3 9/9] mtd: spi-nor: Introduce templates for SPI NOR operations
  2022-04-11  9:10 ` Tudor Ambarus
@ 2022-04-11  9:10   ` Tudor Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Clean the op declaration and hide the details of each op. With this it
results a cleanner, easier to read code. No functional change expected.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
v3: new patch taken from, no changes
https://lore.kernel.org/lkml/20220304093011.198173-1-tudor.ambarus@microchip.com/

 drivers/mtd/spi-nor/core.c      | 101 ++++++-------------------------
 drivers/mtd/spi-nor/core.h      | 102 ++++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/micron-st.c |  24 ++++----
 drivers/mtd/spi-nor/spansion.c  |  26 +++++---
 drivers/mtd/spi-nor/xilinx.c    |  12 ++--
 5 files changed, 158 insertions(+), 107 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 42794328d3b6..fe853532204c 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -359,11 +359,7 @@ int spi_nor_write_enable(struct spi_nor *nor)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_WREN_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -390,11 +386,7 @@ int spi_nor_write_disable(struct spi_nor *nor)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_WRDI_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -454,11 +446,7 @@ int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, sr, 0));
+		struct spi_mem_op op = SPI_NOR_RDSR_OP(sr);
 
 		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
 			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
@@ -498,11 +486,7 @@ int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, cr, 0));
+		struct spi_mem_op op = SPI_NOR_RDCR_OP(cr);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -531,14 +515,7 @@ int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(enable ?
-						  SPINOR_OP_EN4B :
-						  SPINOR_OP_EX4B,
-						  0),
-				  SPI_MEM_OP_NO_ADDR,
-				  SPI_MEM_OP_NO_DUMMY,
-				  SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_EN4B_EX4B_OP(enable);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -572,11 +549,7 @@ static int spansion_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
 	nor->bouncebuf[0] = enable << 7;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 0));
+		struct spi_mem_op op = SPI_NOR_BRWR_OP(nor->bouncebuf);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -606,11 +579,7 @@ int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
 	nor->bouncebuf[0] = ear;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 0));
+		struct spi_mem_op op = SPI_NOR_WREAR_OP(nor->bouncebuf);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -721,11 +690,7 @@ int spi_nor_global_block_unlock(struct spi_nor *nor)
 		return ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_GBULK, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_GBULK_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -760,11 +725,7 @@ int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len)
 		return ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(len, sr, 0));
+		struct spi_mem_op op = SPI_NOR_WRSR_OP(sr, len);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -964,11 +925,7 @@ static int spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2)
 		return ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, sr2, 0));
+		struct spi_mem_op op = SPI_NOR_WRSR2_OP(sr2);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -1000,11 +957,7 @@ static int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, sr2, 0));
+		struct spi_mem_op op = SPI_NOR_RDSR2_OP(sr2);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -1033,11 +986,7 @@ static int spi_nor_erase_chip(struct spi_nor *nor)
 	dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10));
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_CHIP_ERASE_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
 
@@ -1179,10 +1128,8 @@ int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
 
 	if (nor->spimem) {
 		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(nor->erase_opcode, 0),
-				   SPI_MEM_OP_ADDR(nor->addr_width, addr, 0),
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+			SPI_NOR_SECTOR_ERASE_OP(nor->erase_opcode,
+						nor->addr_width, addr);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
 
@@ -1978,10 +1925,7 @@ static int spi_nor_spimem_check_op(struct spi_nor *nor,
 static int spi_nor_spimem_check_readop(struct spi_nor *nor,
 				       const struct spi_nor_read_command *read)
 {
-	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(read->opcode, 0),
-					  SPI_MEM_OP_ADDR(3, 0, 0),
-					  SPI_MEM_OP_DUMMY(1, 0),
-					  SPI_MEM_OP_DATA_IN(2, NULL, 0));
+	struct spi_mem_op op = SPI_NOR_READ_OP(read->opcode);
 
 	spi_nor_spimem_setup_op(nor, &op, read->proto);
 
@@ -2004,10 +1948,7 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor,
 static int spi_nor_spimem_check_pp(struct spi_nor *nor,
 				   const struct spi_nor_pp_command *pp)
 {
-	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(pp->opcode, 0),
-					  SPI_MEM_OP_ADDR(3, 0, 0),
-					  SPI_MEM_OP_NO_DUMMY,
-					  SPI_MEM_OP_DATA_OUT(2, NULL, 0));
+	struct spi_mem_op op = SPI_NOR_PP_OP(pp->opcode);
 
 	spi_nor_spimem_setup_op(nor, &op, pp->proto);
 
@@ -2831,10 +2772,7 @@ static void spi_nor_soft_reset(struct spi_nor *nor)
 	struct spi_mem_op op;
 	int ret;
 
-	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 0),
-			SPI_MEM_OP_NO_DUMMY,
-			SPI_MEM_OP_NO_ADDR,
-			SPI_MEM_OP_NO_DATA);
+	op = (struct spi_mem_op)SPINOR_SRSTEN_OP;
 
 	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -2844,10 +2782,7 @@ static void spi_nor_soft_reset(struct spi_nor *nor)
 		return;
 	}
 
-	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRST, 0),
-			SPI_MEM_OP_NO_DUMMY,
-			SPI_MEM_OP_NO_ADDR,
-			SPI_MEM_OP_NO_DATA);
+	op = (struct spi_mem_op)SPINOR_SRST_OP;
 
 	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 7c704475946d..8b7e597fd38c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -18,6 +18,108 @@
 		   SPI_MEM_OP_DUMMY(ndummy, 0),				\
 		   SPI_MEM_OP_DATA_IN(len, buf, 0))
 
+#define SPI_NOR_WREN_OP							\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_WRDI_OP							\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_RDSR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+#define SPI_NOR_WRSR_OP(buf, len)					\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(len, buf, 0))
+
+#define SPI_NOR_RDSR2_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
+
+#define SPI_NOR_WRSR2_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
+
+#define SPI_NOR_RDCR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+#define SPI_NOR_EN4B_EX4B_OP(enable)					\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, 0),	\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_BRWR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
+
+#define SPI_NOR_WREAR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
+
+#define SPI_NOR_GBULK_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_GBULK, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_CHIP_ERASE_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),		\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_SECTOR_ERASE_OP(opcode, addr_width, addr)		\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
+		   SPI_MEM_OP_ADDR(addr_width, addr, 0),		\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_READ_OP(opcode)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
+		   SPI_MEM_OP_ADDR(3, 0, 0),				\
+		   SPI_MEM_OP_DUMMY(1, 0),				\
+		   SPI_MEM_OP_DATA_IN(2, NULL, 0))
+
+#define SPI_NOR_PP_OP(opcode)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
+		   SPI_MEM_OP_ADDR(3, 0, 0),				\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(2, NULL, 0))
+
+#define SPINOR_SRSTEN_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPINOR_SRST_OP							\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRST, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DATA)
+
 enum spi_nor_option_flags {
 	SNOR_F_HAS_SR_TB	= BIT(0),
 	SNOR_F_NO_OP_CHIP_ERASE	= BIT(1),
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index a447762c0d78..26b9a1c2309d 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -35,6 +35,18 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
 
+#define MICRON_ST_RDFSR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+#define MICRON_ST_CLFSR_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
@@ -324,11 +336,7 @@ static int micron_st_nor_read_fsr(struct spi_nor *nor, u8 *fsr)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, fsr, 0));
+		struct spi_mem_op op = MICRON_ST_RDFSR_OP(fsr);
 
 		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
 			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
@@ -363,11 +371,7 @@ static void micron_st_nor_clear_fsr(struct spi_nor *nor)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = MICRON_ST_CLFSR_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 35d8edb515a3..952db7af6932 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -30,6 +30,18 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
 
+#define CYPRESS_NOR_RD_ANY_REG_OP(naddr, addr, buf)			\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0),		\
+		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+#define SPANSION_CLSR_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
@@ -165,12 +177,12 @@ static int s28hs512t_post_bfpt_fixup(struct spi_nor *nor,
 	 * CFR3V[4] and set the correct size.
 	 */
 	struct spi_mem_op op =
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1),
-			   SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR3V, 1),
-			   SPI_MEM_OP_NO_DUMMY,
-			   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
+		CYPRESS_NOR_RD_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR3V,
+					  nor->bouncebuf);
 	int ret;
 
+	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
 	ret = spi_mem_exec_op(nor->spimem, &op);
 	if (ret)
 		return ret;
@@ -320,11 +332,7 @@ static void spansion_nor_clear_sr(struct spi_nor *nor)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPANSION_CLSR_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
index 9459ac2609dc..1d2f5db047bd 100644
--- a/drivers/mtd/spi-nor/xilinx.c
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -15,6 +15,12 @@
 #define XSR_PAGESIZE		BIT(0)	/* Page size in Po2 or Linear */
 #define XSR_RDY			BIT(7)	/* Ready */
 
+#define XILINX_RDSR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
 #define S3AN_INFO(_jedec_id, _n_sectors, _page_size)			\
 		.id = {							\
 			((_jedec_id) >> 16) & 0xff,			\
@@ -72,11 +78,7 @@ static int xilinx_nor_read_sr(struct spi_nor *nor, u8 *sr)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, sr, 0));
+		struct spi_mem_op op = XILINX_RDSR_OP(sr);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
-- 
2.25.1


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

* [PATCH v3 9/9] mtd: spi-nor: Introduce templates for SPI NOR operations
@ 2022-04-11  9:10   ` Tudor Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor Ambarus @ 2022-04-11  9:10 UTC (permalink / raw)
  To: p.yadav, michael
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	nicolas.ferre, Tudor Ambarus

Clean the op declaration and hide the details of each op. With this it
results a cleanner, easier to read code. No functional change expected.

Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
---
v3: new patch taken from, no changes
https://lore.kernel.org/lkml/20220304093011.198173-1-tudor.ambarus@microchip.com/

 drivers/mtd/spi-nor/core.c      | 101 ++++++-------------------------
 drivers/mtd/spi-nor/core.h      | 102 ++++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/micron-st.c |  24 ++++----
 drivers/mtd/spi-nor/spansion.c  |  26 +++++---
 drivers/mtd/spi-nor/xilinx.c    |  12 ++--
 5 files changed, 158 insertions(+), 107 deletions(-)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index 42794328d3b6..fe853532204c 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -359,11 +359,7 @@ int spi_nor_write_enable(struct spi_nor *nor)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_WREN_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -390,11 +386,7 @@ int spi_nor_write_disable(struct spi_nor *nor)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_WRDI_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -454,11 +446,7 @@ int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, sr, 0));
+		struct spi_mem_op op = SPI_NOR_RDSR_OP(sr);
 
 		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
 			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
@@ -498,11 +486,7 @@ int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, cr, 0));
+		struct spi_mem_op op = SPI_NOR_RDCR_OP(cr);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -531,14 +515,7 @@ int spi_nor_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(enable ?
-						  SPINOR_OP_EN4B :
-						  SPINOR_OP_EX4B,
-						  0),
-				  SPI_MEM_OP_NO_ADDR,
-				  SPI_MEM_OP_NO_DUMMY,
-				  SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_EN4B_EX4B_OP(enable);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -572,11 +549,7 @@ static int spansion_set_4byte_addr_mode(struct spi_nor *nor, bool enable)
 	nor->bouncebuf[0] = enable << 7;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 0));
+		struct spi_mem_op op = SPI_NOR_BRWR_OP(nor->bouncebuf);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -606,11 +579,7 @@ int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
 	nor->bouncebuf[0] = ear;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 0));
+		struct spi_mem_op op = SPI_NOR_WREAR_OP(nor->bouncebuf);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -721,11 +690,7 @@ int spi_nor_global_block_unlock(struct spi_nor *nor)
 		return ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_GBULK, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_GBULK_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -760,11 +725,7 @@ int spi_nor_write_sr(struct spi_nor *nor, const u8 *sr, size_t len)
 		return ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(len, sr, 0));
+		struct spi_mem_op op = SPI_NOR_WRSR_OP(sr, len);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -964,11 +925,7 @@ static int spi_nor_write_sr2(struct spi_nor *nor, const u8 *sr2)
 		return ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_OUT(1, sr2, 0));
+		struct spi_mem_op op = SPI_NOR_WRSR2_OP(sr2);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -1000,11 +957,7 @@ static int spi_nor_read_sr2(struct spi_nor *nor, u8 *sr2)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, sr2, 0));
+		struct spi_mem_op op = SPI_NOR_RDSR2_OP(sr2);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -1033,11 +986,7 @@ static int spi_nor_erase_chip(struct spi_nor *nor)
 	dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10));
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPI_NOR_CHIP_ERASE_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
 
@@ -1179,10 +1128,8 @@ int spi_nor_erase_sector(struct spi_nor *nor, u32 addr)
 
 	if (nor->spimem) {
 		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(nor->erase_opcode, 0),
-				   SPI_MEM_OP_ADDR(nor->addr_width, addr, 0),
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+			SPI_NOR_SECTOR_ERASE_OP(nor->erase_opcode,
+						nor->addr_width, addr);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
 
@@ -1978,10 +1925,7 @@ static int spi_nor_spimem_check_op(struct spi_nor *nor,
 static int spi_nor_spimem_check_readop(struct spi_nor *nor,
 				       const struct spi_nor_read_command *read)
 {
-	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(read->opcode, 0),
-					  SPI_MEM_OP_ADDR(3, 0, 0),
-					  SPI_MEM_OP_DUMMY(1, 0),
-					  SPI_MEM_OP_DATA_IN(2, NULL, 0));
+	struct spi_mem_op op = SPI_NOR_READ_OP(read->opcode);
 
 	spi_nor_spimem_setup_op(nor, &op, read->proto);
 
@@ -2004,10 +1948,7 @@ static int spi_nor_spimem_check_readop(struct spi_nor *nor,
 static int spi_nor_spimem_check_pp(struct spi_nor *nor,
 				   const struct spi_nor_pp_command *pp)
 {
-	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(pp->opcode, 0),
-					  SPI_MEM_OP_ADDR(3, 0, 0),
-					  SPI_MEM_OP_NO_DUMMY,
-					  SPI_MEM_OP_DATA_OUT(2, NULL, 0));
+	struct spi_mem_op op = SPI_NOR_PP_OP(pp->opcode);
 
 	spi_nor_spimem_setup_op(nor, &op, pp->proto);
 
@@ -2831,10 +2772,7 @@ static void spi_nor_soft_reset(struct spi_nor *nor)
 	struct spi_mem_op op;
 	int ret;
 
-	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 0),
-			SPI_MEM_OP_NO_DUMMY,
-			SPI_MEM_OP_NO_ADDR,
-			SPI_MEM_OP_NO_DATA);
+	op = (struct spi_mem_op)SPINOR_SRSTEN_OP;
 
 	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
@@ -2844,10 +2782,7 @@ static void spi_nor_soft_reset(struct spi_nor *nor)
 		return;
 	}
 
-	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRST, 0),
-			SPI_MEM_OP_NO_DUMMY,
-			SPI_MEM_OP_NO_ADDR,
-			SPI_MEM_OP_NO_DATA);
+	op = (struct spi_mem_op)SPINOR_SRST_OP;
 
 	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 7c704475946d..8b7e597fd38c 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -18,6 +18,108 @@
 		   SPI_MEM_OP_DUMMY(ndummy, 0),				\
 		   SPI_MEM_OP_DATA_IN(len, buf, 0))
 
+#define SPI_NOR_WREN_OP							\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_WRDI_OP							\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_RDSR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+#define SPI_NOR_WRSR_OP(buf, len)					\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(len, buf, 0))
+
+#define SPI_NOR_RDSR2_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
+
+#define SPI_NOR_WRSR2_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
+
+#define SPI_NOR_RDCR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+#define SPI_NOR_EN4B_EX4B_OP(enable)					\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, 0),	\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_BRWR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
+
+#define SPI_NOR_WREAR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
+
+#define SPI_NOR_GBULK_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_GBULK, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_CHIP_ERASE_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),		\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_SECTOR_ERASE_OP(opcode, addr_width, addr)		\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
+		   SPI_MEM_OP_ADDR(addr_width, addr, 0),		\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPI_NOR_READ_OP(opcode)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
+		   SPI_MEM_OP_ADDR(3, 0, 0),				\
+		   SPI_MEM_OP_DUMMY(1, 0),				\
+		   SPI_MEM_OP_DATA_IN(2, NULL, 0))
+
+#define SPI_NOR_PP_OP(opcode)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
+		   SPI_MEM_OP_ADDR(3, 0, 0),				\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_OUT(2, NULL, 0))
+
+#define SPINOR_SRSTEN_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DATA)
+
+#define SPINOR_SRST_OP							\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRST, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DATA)
+
 enum spi_nor_option_flags {
 	SNOR_F_HAS_SR_TB	= BIT(0),
 	SNOR_F_NO_OP_CHIP_ERASE	= BIT(1),
diff --git a/drivers/mtd/spi-nor/micron-st.c b/drivers/mtd/spi-nor/micron-st.c
index a447762c0d78..26b9a1c2309d 100644
--- a/drivers/mtd/spi-nor/micron-st.c
+++ b/drivers/mtd/spi-nor/micron-st.c
@@ -35,6 +35,18 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
 
+#define MICRON_ST_RDFSR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+#define MICRON_ST_CLFSR_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
@@ -324,11 +336,7 @@ static int micron_st_nor_read_fsr(struct spi_nor *nor, u8 *fsr)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, fsr, 0));
+		struct spi_mem_op op = MICRON_ST_RDFSR_OP(fsr);
 
 		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
 			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
@@ -363,11 +371,7 @@ static void micron_st_nor_clear_fsr(struct spi_nor *nor)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = MICRON_ST_CLFSR_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c
index 35d8edb515a3..952db7af6932 100644
--- a/drivers/mtd/spi-nor/spansion.c
+++ b/drivers/mtd/spi-nor/spansion.c
@@ -30,6 +30,18 @@
 		   SPI_MEM_OP_NO_DUMMY,					\
 		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
 
+#define CYPRESS_NOR_RD_ANY_REG_OP(naddr, addr, buf)			\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0),		\
+		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
+#define SPANSION_CLSR_OP						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_NO_DATA)
+
 static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
 {
 	struct spi_mem_op op;
@@ -165,12 +177,12 @@ static int s28hs512t_post_bfpt_fixup(struct spi_nor *nor,
 	 * CFR3V[4] and set the correct size.
 	 */
 	struct spi_mem_op op =
-		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1),
-			   SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR3V, 1),
-			   SPI_MEM_OP_NO_DUMMY,
-			   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
+		CYPRESS_NOR_RD_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR3V,
+					  nor->bouncebuf);
 	int ret;
 
+	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
+
 	ret = spi_mem_exec_op(nor->spimem, &op);
 	if (ret)
 		return ret;
@@ -320,11 +332,7 @@ static void spansion_nor_clear_sr(struct spi_nor *nor)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_NO_DATA);
+		struct spi_mem_op op = SPANSION_CLSR_OP;
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
diff --git a/drivers/mtd/spi-nor/xilinx.c b/drivers/mtd/spi-nor/xilinx.c
index 9459ac2609dc..1d2f5db047bd 100644
--- a/drivers/mtd/spi-nor/xilinx.c
+++ b/drivers/mtd/spi-nor/xilinx.c
@@ -15,6 +15,12 @@
 #define XSR_PAGESIZE		BIT(0)	/* Page size in Po2 or Linear */
 #define XSR_RDY			BIT(7)	/* Ready */
 
+#define XILINX_RDSR_OP(buf)						\
+	SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),			\
+		   SPI_MEM_OP_NO_ADDR,					\
+		   SPI_MEM_OP_NO_DUMMY,					\
+		   SPI_MEM_OP_DATA_IN(1, buf, 0))
+
 #define S3AN_INFO(_jedec_id, _n_sectors, _page_size)			\
 		.id = {							\
 			((_jedec_id) >> 16) & 0xff,			\
@@ -72,11 +78,7 @@ static int xilinx_nor_read_sr(struct spi_nor *nor, u8 *sr)
 	int ret;
 
 	if (nor->spimem) {
-		struct spi_mem_op op =
-			SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),
-				   SPI_MEM_OP_NO_ADDR,
-				   SPI_MEM_OP_NO_DUMMY,
-				   SPI_MEM_OP_DATA_IN(1, sr, 0));
+		struct spi_mem_op op = XILINX_RDSR_OP(sr);
 
 		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
 
-- 
2.25.1


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

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

* Re: [PATCH v3 3/9] mtd: spi-nor: core: Use auto-detection only once
  2022-04-11  9:10   ` Tudor Ambarus
@ 2022-04-19 10:18     ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 10:18 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> In case spi_nor_match_name() returned NULL, the auto detection was
> issued twice. There's no reason to try to detect the same chip twice,
> do the auto detection only once.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
> v3:
> - caller of spi_nor_get_flash_info now handles NULL and translates it 
> to
> ENOENT.
> 
>  drivers/mtd/spi-nor/core.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index b9cc8bbf1f62..b55d922d46dd 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -2896,13 +2896,14 @@ static const struct flash_info
> *spi_nor_get_flash_info(struct spi_nor *nor,
>  {
>  	const struct flash_info *info = NULL;
> 
> -	if (name)
> +	if (name) {
>  		info = spi_nor_match_name(nor, name);
> +		if (IS_ERR(info))
> +			return info;
> +	}

That is unnecessary, as spi_nor_match_name() doesn't
return an error code, just NULL or a valid pointer.

Apart from that:
Reviewed-by: Michael Walle <michael@walle.cc>

>  	/* Try to auto-detect if chip name wasn't specified or not found */
>  	if (!info)
> -		info = spi_nor_read_id(nor);
> -	if (IS_ERR_OR_NULL(info))
> -		return ERR_PTR(-ENOENT);
> +		return spi_nor_read_id(nor);
> 
>  	/*
>  	 * If caller has specified name of flash model that can normally be
> @@ -2994,7 +2995,9 @@ int spi_nor_scan(struct spi_nor *nor, const char 
> *name,
>  		return -ENOMEM;
> 
>  	info = spi_nor_get_flash_info(nor, name);
> -	if (IS_ERR(info))
> +	if (!info)
> +		return -ENOENT;
> +	else if (IS_ERR(info))
>  		return PTR_ERR(info);
> 
>  	nor->info = info;

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

* Re: [PATCH v3 3/9] mtd: spi-nor: core: Use auto-detection only once
@ 2022-04-19 10:18     ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 10:18 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> In case spi_nor_match_name() returned NULL, the auto detection was
> issued twice. There's no reason to try to detect the same chip twice,
> do the auto detection only once.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
> v3:
> - caller of spi_nor_get_flash_info now handles NULL and translates it 
> to
> ENOENT.
> 
>  drivers/mtd/spi-nor/core.c | 13 ++++++++-----
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index b9cc8bbf1f62..b55d922d46dd 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -2896,13 +2896,14 @@ static const struct flash_info
> *spi_nor_get_flash_info(struct spi_nor *nor,
>  {
>  	const struct flash_info *info = NULL;
> 
> -	if (name)
> +	if (name) {
>  		info = spi_nor_match_name(nor, name);
> +		if (IS_ERR(info))
> +			return info;
> +	}

That is unnecessary, as spi_nor_match_name() doesn't
return an error code, just NULL or a valid pointer.

Apart from that:
Reviewed-by: Michael Walle <michael@walle.cc>

>  	/* Try to auto-detect if chip name wasn't specified or not found */
>  	if (!info)
> -		info = spi_nor_read_id(nor);
> -	if (IS_ERR_OR_NULL(info))
> -		return ERR_PTR(-ENOENT);
> +		return spi_nor_read_id(nor);
> 
>  	/*
>  	 * If caller has specified name of flash model that can normally be
> @@ -2994,7 +2995,9 @@ int spi_nor_scan(struct spi_nor *nor, const char 
> *name,
>  		return -ENOMEM;
> 
>  	info = spi_nor_get_flash_info(nor, name);
> -	if (IS_ERR(info))
> +	if (!info)
> +		return -ENOENT;
> +	else if (IS_ERR(info))
>  		return PTR_ERR(info);
> 
>  	nor->info = info;

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

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

* Re: [PATCH v3 4/9] mtd: spi-nor: core: Introduce method for RDID op
  2022-04-11  9:10   ` Tudor Ambarus
@ 2022-04-19 11:10     ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:10 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> RDID is used in the core to auto detect the flash, but also by some
> manufacturer drivers that contain flashes that support Octal DTR mode,
> so that they can read the flash ID after the switch to Octal DTR was 
> made
> to test if the switch was successful. Introduce a core method for RDID 
> op
> to avoid code duplication.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
> v3: s/reg_proto/proto
> 
>  drivers/mtd/spi-nor/core.c | 50 ++++++++++++++++++++++++++------------
>  drivers/mtd/spi-nor/core.h |  9 +++++++
>  2 files changed, 44 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index b55d922d46dd..6165dc7bfd17 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -369,6 +369,37 @@ int spi_nor_write_disable(struct spi_nor *nor)
>  	return ret;
>  }
> 
> +/**
> + * spi_nor_read_id() - Read the JEDEC ID.
> + * @nor:	pointer to 'struct spi_nor'.
> + * @naddr:	number of address bytes to send. Can be zero if the 
> operation
> + *		does not need to send an address.
> + * @ndummy:	number of dummy bytes to send after an opcode or address. 
> Can
> + *		be zero if the operation does not require dummy bytes.
> + * @id:		pointer to a DMA-able buffer where the value of the JEDEC ID
> + *		will be written.
> + * @proto:	the SPI protocol for register operation.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +int spi_nor_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
> +		    enum spi_nor_protocol proto)

I'm unsure on the last parameter, no other call have it.
The usual pattern is

old_proto = nor->reg_proto;
spi_nor_read_id();
nor->reg_proto = old_proto;

But I don't care too much.

Reviewed-by: Michael Walle <michael@walle.cc>

> +{
> +	int ret;
> +
> +	if (nor->spimem) {
> +		struct spi_mem_op op =
> +			SPI_NOR_READID_OP(naddr, ndummy, id, SPI_NOR_MAX_ID_LEN);
> +
> +		spi_nor_spimem_setup_op(nor, &op, proto);
> +		ret = spi_mem_exec_op(nor->spimem, &op);
> +	} else {
> +		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
> +						    SPI_NOR_MAX_ID_LEN);
> +	}
> +	return ret;
> +}
> +
>  /**
>   * spi_nor_read_sr() - Read the Status Register.
>   * @nor:	pointer to 'struct spi_nor'.
> @@ -1649,24 +1680,13 @@ static const struct flash_info
> *spi_nor_match_id(struct spi_nor *nor,
>  	return NULL;
>  }
> 
> -static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
> +static const struct flash_info *spi_nor_detect(struct spi_nor *nor)
>  {
>  	const struct flash_info *info;
>  	u8 *id = nor->bouncebuf;
>  	int ret;
> 
> -	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(SPI_NOR_MAX_ID_LEN, id, 1));
> -
> -		ret = spi_mem_exec_op(nor->spimem, &op);
> -	} else {
> -		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
> -						    SPI_NOR_MAX_ID_LEN);
> -	}
> +	ret = spi_nor_read_id(nor, 0, 0, id, nor->reg_proto);
>  	if (ret) {
>  		dev_dbg(nor->dev, "error %d reading JEDEC ID\n", ret);
>  		return ERR_PTR(ret);
> @@ -2903,7 +2923,7 @@ static const struct flash_info
> *spi_nor_get_flash_info(struct spi_nor *nor,
>  	}
>  	/* Try to auto-detect if chip name wasn't specified or not found */
>  	if (!info)
> -		return spi_nor_read_id(nor);
> +		return spi_nor_detect(nor);
> 
>  	/*
>  	 * If caller has specified name of flash model that can normally be
> @@ -2912,7 +2932,7 @@ static const struct flash_info
> *spi_nor_get_flash_info(struct spi_nor *nor,
>  	if (name && info->id_len) {
>  		const struct flash_info *jinfo;
> 
> -		jinfo = spi_nor_read_id(nor);
> +		jinfo = spi_nor_detect(nor);
>  		if (IS_ERR(jinfo)) {
>  			return jinfo;
>  		} else if (jinfo != info) {
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index b7fd760e3b47..f952061d5c24 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -11,6 +11,13 @@
> 
>  #define SPI_NOR_MAX_ID_LEN	6
> 
> +/* Standard SPI NOR flash operations. */
> +#define SPI_NOR_READID_OP(naddr, ndummy, buf, len)			\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 0),			\
> +		   SPI_MEM_OP_ADDR(naddr, 0, 0),			\
> +		   SPI_MEM_OP_DUMMY(ndummy, 0),				\
> +		   SPI_MEM_OP_DATA_IN(len, buf, 0))
> +
>  enum spi_nor_option_flags {
>  	SNOR_F_HAS_SR_TB	= BIT(0),
>  	SNOR_F_NO_OP_CHIP_ERASE	= BIT(1),
> @@ -534,6 +541,8 @@ 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_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
> +		    enum spi_nor_protocol reg_proto);
>  int spi_nor_read_sr(struct spi_nor *nor, u8 *sr);
>  int spi_nor_sr_ready(struct spi_nor *nor);
>  int spi_nor_read_cr(struct spi_nor *nor, u8 *cr);

-- 
-michael

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

* Re: [PATCH v3 4/9] mtd: spi-nor: core: Introduce method for RDID op
@ 2022-04-19 11:10     ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:10 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> RDID is used in the core to auto detect the flash, but also by some
> manufacturer drivers that contain flashes that support Octal DTR mode,
> so that they can read the flash ID after the switch to Octal DTR was 
> made
> to test if the switch was successful. Introduce a core method for RDID 
> op
> to avoid code duplication.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> ---
> v3: s/reg_proto/proto
> 
>  drivers/mtd/spi-nor/core.c | 50 ++++++++++++++++++++++++++------------
>  drivers/mtd/spi-nor/core.h |  9 +++++++
>  2 files changed, 44 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index b55d922d46dd..6165dc7bfd17 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -369,6 +369,37 @@ int spi_nor_write_disable(struct spi_nor *nor)
>  	return ret;
>  }
> 
> +/**
> + * spi_nor_read_id() - Read the JEDEC ID.
> + * @nor:	pointer to 'struct spi_nor'.
> + * @naddr:	number of address bytes to send. Can be zero if the 
> operation
> + *		does not need to send an address.
> + * @ndummy:	number of dummy bytes to send after an opcode or address. 
> Can
> + *		be zero if the operation does not require dummy bytes.
> + * @id:		pointer to a DMA-able buffer where the value of the JEDEC ID
> + *		will be written.
> + * @proto:	the SPI protocol for register operation.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +int spi_nor_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
> +		    enum spi_nor_protocol proto)

I'm unsure on the last parameter, no other call have it.
The usual pattern is

old_proto = nor->reg_proto;
spi_nor_read_id();
nor->reg_proto = old_proto;

But I don't care too much.

Reviewed-by: Michael Walle <michael@walle.cc>

> +{
> +	int ret;
> +
> +	if (nor->spimem) {
> +		struct spi_mem_op op =
> +			SPI_NOR_READID_OP(naddr, ndummy, id, SPI_NOR_MAX_ID_LEN);
> +
> +		spi_nor_spimem_setup_op(nor, &op, proto);
> +		ret = spi_mem_exec_op(nor->spimem, &op);
> +	} else {
> +		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
> +						    SPI_NOR_MAX_ID_LEN);
> +	}
> +	return ret;
> +}
> +
>  /**
>   * spi_nor_read_sr() - Read the Status Register.
>   * @nor:	pointer to 'struct spi_nor'.
> @@ -1649,24 +1680,13 @@ static const struct flash_info
> *spi_nor_match_id(struct spi_nor *nor,
>  	return NULL;
>  }
> 
> -static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
> +static const struct flash_info *spi_nor_detect(struct spi_nor *nor)
>  {
>  	const struct flash_info *info;
>  	u8 *id = nor->bouncebuf;
>  	int ret;
> 
> -	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(SPI_NOR_MAX_ID_LEN, id, 1));
> -
> -		ret = spi_mem_exec_op(nor->spimem, &op);
> -	} else {
> -		ret = nor->controller_ops->read_reg(nor, SPINOR_OP_RDID, id,
> -						    SPI_NOR_MAX_ID_LEN);
> -	}
> +	ret = spi_nor_read_id(nor, 0, 0, id, nor->reg_proto);
>  	if (ret) {
>  		dev_dbg(nor->dev, "error %d reading JEDEC ID\n", ret);
>  		return ERR_PTR(ret);
> @@ -2903,7 +2923,7 @@ static const struct flash_info
> *spi_nor_get_flash_info(struct spi_nor *nor,
>  	}
>  	/* Try to auto-detect if chip name wasn't specified or not found */
>  	if (!info)
> -		return spi_nor_read_id(nor);
> +		return spi_nor_detect(nor);
> 
>  	/*
>  	 * If caller has specified name of flash model that can normally be
> @@ -2912,7 +2932,7 @@ static const struct flash_info
> *spi_nor_get_flash_info(struct spi_nor *nor,
>  	if (name && info->id_len) {
>  		const struct flash_info *jinfo;
> 
> -		jinfo = spi_nor_read_id(nor);
> +		jinfo = spi_nor_detect(nor);
>  		if (IS_ERR(jinfo)) {
>  			return jinfo;
>  		} else if (jinfo != info) {
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index b7fd760e3b47..f952061d5c24 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -11,6 +11,13 @@
> 
>  #define SPI_NOR_MAX_ID_LEN	6
> 
> +/* Standard SPI NOR flash operations. */
> +#define SPI_NOR_READID_OP(naddr, ndummy, buf, len)			\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 0),			\
> +		   SPI_MEM_OP_ADDR(naddr, 0, 0),			\
> +		   SPI_MEM_OP_DUMMY(ndummy, 0),				\
> +		   SPI_MEM_OP_DATA_IN(len, buf, 0))
> +
>  enum spi_nor_option_flags {
>  	SNOR_F_HAS_SR_TB	= BIT(0),
>  	SNOR_F_NO_OP_CHIP_ERASE	= BIT(1),
> @@ -534,6 +541,8 @@ 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_read_id(struct spi_nor *nor, u8 naddr, u8 ndummy, u8 *id,
> +		    enum spi_nor_protocol reg_proto);
>  int spi_nor_read_sr(struct spi_nor *nor, u8 *sr);
>  int spi_nor_sr_ready(struct spi_nor *nor);
>  int spi_nor_read_cr(struct spi_nor *nor, u8 *cr);

-- 
-michael

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

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

* Re: [PATCH v3 5/9] mtd: spi-nor: manufacturers: Use spi_nor_read_id() core method
  2022-04-11  9:10   ` Tudor Ambarus
@ 2022-04-19 11:14     ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:14 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> Use spi_nor_read_id() core method to avoid duplication of code. Now the 
> ID
> is read on the full SPI_NOR_MAX_ID_LEN instead of
> round_up(nor->info->id_len, 2), but it doesn't harm to read more ID 
> bytes,
> so the change comes with no secondary effects. dev_dbg messages in case
> spi_nor_read_id() fails, will be added in a further patch after we 
> split
> the octal DTR enable/disable methods.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

I like it, but maybe add a

/* SPI_NOR_MAX_ID_LEN is also used for octal readid and needs to be even 
*/
static_assert(SPI_NOR_MAX_ID_LEN % 2 == 0);

Reviewed-by: Michael Walle <michael@walle.cc>

> ---
> v3: collect R-b, update commit message
> 
>  drivers/mtd/spi-nor/micron-st.c | 13 +++----------
>  drivers/mtd/spi-nor/spansion.c  | 13 +++----------
>  2 files changed, 6 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/micron-st.c 
> b/drivers/mtd/spi-nor/micron-st.c
> index 8a20475ce77a..41b87868ecf9 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -91,17 +91,10 @@ static int micron_st_nor_octal_dtr_enable(struct
> spi_nor *nor, bool enable)
>  		return ret;
> 
>  	/* Read flash ID to make sure the switch was successful. */
> -	op = (struct spi_mem_op)
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
> -			   SPI_MEM_OP_NO_ADDR,
> -			   SPI_MEM_OP_DUMMY(enable ? 8 : 0, 1),
> -			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
> -					      buf, 1));
> -
>  	if (enable)
> -		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
> -
> -	ret = spi_mem_exec_op(nor->spimem, &op);
> +		ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
> +	else
> +		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
>  	if (ret)
>  		return ret;
> 
> diff --git a/drivers/mtd/spi-nor/spansion.c 
> b/drivers/mtd/spi-nor/spansion.c
> index f24e546e04a5..c5988312cc91 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -98,17 +98,10 @@ static int cypress_nor_octal_dtr_enable(struct
> spi_nor *nor, bool enable)
>  		return ret;
> 
>  	/* Read flash ID to make sure the switch was successful. */
> -	op = (struct spi_mem_op)
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
> -			   SPI_MEM_OP_ADDR(enable ? 4 : 0, 0, 1),
> -			   SPI_MEM_OP_DUMMY(enable ? 3 : 0, 1),
> -			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
> -					      buf, 1));
> -
>  	if (enable)
> -		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
> -
> -	ret = spi_mem_exec_op(nor->spimem, &op);
> +		ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
> +	else
> +		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
>  	if (ret)
>  		return ret;

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

* Re: [PATCH v3 5/9] mtd: spi-nor: manufacturers: Use spi_nor_read_id() core method
@ 2022-04-19 11:14     ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:14 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> Use spi_nor_read_id() core method to avoid duplication of code. Now the 
> ID
> is read on the full SPI_NOR_MAX_ID_LEN instead of
> round_up(nor->info->id_len, 2), but it doesn't harm to read more ID 
> bytes,
> so the change comes with no secondary effects. dev_dbg messages in case
> spi_nor_read_id() fails, will be added in a further patch after we 
> split
> the octal DTR enable/disable methods.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

I like it, but maybe add a

/* SPI_NOR_MAX_ID_LEN is also used for octal readid and needs to be even 
*/
static_assert(SPI_NOR_MAX_ID_LEN % 2 == 0);

Reviewed-by: Michael Walle <michael@walle.cc>

> ---
> v3: collect R-b, update commit message
> 
>  drivers/mtd/spi-nor/micron-st.c | 13 +++----------
>  drivers/mtd/spi-nor/spansion.c  | 13 +++----------
>  2 files changed, 6 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/micron-st.c 
> b/drivers/mtd/spi-nor/micron-st.c
> index 8a20475ce77a..41b87868ecf9 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -91,17 +91,10 @@ static int micron_st_nor_octal_dtr_enable(struct
> spi_nor *nor, bool enable)
>  		return ret;
> 
>  	/* Read flash ID to make sure the switch was successful. */
> -	op = (struct spi_mem_op)
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
> -			   SPI_MEM_OP_NO_ADDR,
> -			   SPI_MEM_OP_DUMMY(enable ? 8 : 0, 1),
> -			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
> -					      buf, 1));
> -
>  	if (enable)
> -		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
> -
> -	ret = spi_mem_exec_op(nor->spimem, &op);
> +		ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
> +	else
> +		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
>  	if (ret)
>  		return ret;
> 
> diff --git a/drivers/mtd/spi-nor/spansion.c 
> b/drivers/mtd/spi-nor/spansion.c
> index f24e546e04a5..c5988312cc91 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -98,17 +98,10 @@ static int cypress_nor_octal_dtr_enable(struct
> spi_nor *nor, bool enable)
>  		return ret;
> 
>  	/* Read flash ID to make sure the switch was successful. */
> -	op = (struct spi_mem_op)
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDID, 1),
> -			   SPI_MEM_OP_ADDR(enable ? 4 : 0, 0, 1),
> -			   SPI_MEM_OP_DUMMY(enable ? 3 : 0, 1),
> -			   SPI_MEM_OP_DATA_IN(round_up(nor->info->id_len, 2),
> -					      buf, 1));
> -
>  	if (enable)
> -		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
> -
> -	ret = spi_mem_exec_op(nor->spimem, &op);
> +		ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
> +	else
> +		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
>  	if (ret)
>  		return ret;

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-11  9:10   ` Tudor Ambarus
@ 2022-04-19 11:19     ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:19 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre, Takahiro Kuwano

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> There are manufacturers that use registers indexed by address. Some of
> them support "read/write any register" opcodes. Provide core methods 
> that
> can be used by all manufacturers. SPI NOR controller ops are 
> intentionally
> not supported as we intend to move all the SPI NOR controller drivers
> under the SPI subsystem.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

I still don't like it because the function doesn't do
anything what the function name might suggest. The read
just executes an op, the write executes an op with a
write enable before. All the behavior is determined by the
'op' argument.

Anyway,
Reviewed-by: Michael Walle <michael@walle.cc>

> ---
> v3: no changes
> 
>  drivers/mtd/spi-nor/core.c | 41 ++++++++++++++++++++++++++++++++++++++
>  drivers/mtd/spi-nor/core.h |  4 ++++
>  2 files changed, 45 insertions(+)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index 6165dc7bfd17..42794328d3b6 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
> loff_t to, size_t len,
>  	return nor->controller_ops->write(nor, to, len, buf);
>  }
> 
> +/**
> + * spi_nor_read_reg() - read register to flash memory
> + * @nor:        pointer to 'struct spi_nor'.
> + * @op:		SPI memory operation. op->data.buf must be DMA-able.
> + * @proto:	SPI protocol to use for the register operation.
> + *
> + * Return: zero on success, -errno otherwise
> + */
> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
> +		     enum spi_nor_protocol proto)
> +{
> +	if (!nor->spimem)
> +		return -EOPNOTSUPP;
> +
> +	spi_nor_spimem_setup_op(nor, op, proto);
> +	return spi_nor_spimem_exec_op(nor, op);
> +}
> +
> +/**
> + * spi_nor_write_reg() - write register to flash memory
> + * @nor:        pointer to 'struct spi_nor'
> + * @op:		SPI memory operation. op->data.buf must be DMA-able.
> + * @proto:	SPI protocol to use for the register operation.
> + *
> + * Return: zero on success, -errno otherwise
> + */
> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
> +		      enum spi_nor_protocol proto)
> +{
> +	int ret;
> +
> +	if (!nor->spimem)
> +		return -EOPNOTSUPP;
> +
> +	ret = spi_nor_write_enable(nor);
> +	if (ret)
> +		return ret;
> +	spi_nor_spimem_setup_op(nor, op, proto);
> +	return spi_nor_spimem_exec_op(nor, op);
> +}
> +
>  /**
>   * spi_nor_write_enable() - Set write enable latch with Write Enable 
> command.
>   * @nor:	pointer to 'struct spi_nor'.
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index f952061d5c24..7c704475946d 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -554,6 +554,10 @@ 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_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
> +		     enum spi_nor_protocol proto);
> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
> +		      enum spi_nor_protocol proto);
>  int spi_nor_erase_sector(struct spi_nor *nor, u32 addr);
> 
>  int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t
> len, u8 *buf);

-- 
-michael

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-19 11:19     ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:19 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre, Takahiro Kuwano

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> There are manufacturers that use registers indexed by address. Some of
> them support "read/write any register" opcodes. Provide core methods 
> that
> can be used by all manufacturers. SPI NOR controller ops are 
> intentionally
> not supported as we intend to move all the SPI NOR controller drivers
> under the SPI subsystem.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

I still don't like it because the function doesn't do
anything what the function name might suggest. The read
just executes an op, the write executes an op with a
write enable before. All the behavior is determined by the
'op' argument.

Anyway,
Reviewed-by: Michael Walle <michael@walle.cc>

> ---
> v3: no changes
> 
>  drivers/mtd/spi-nor/core.c | 41 ++++++++++++++++++++++++++++++++++++++
>  drivers/mtd/spi-nor/core.h |  4 ++++
>  2 files changed, 45 insertions(+)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index 6165dc7bfd17..42794328d3b6 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
> loff_t to, size_t len,
>  	return nor->controller_ops->write(nor, to, len, buf);
>  }
> 
> +/**
> + * spi_nor_read_reg() - read register to flash memory
> + * @nor:        pointer to 'struct spi_nor'.
> + * @op:		SPI memory operation. op->data.buf must be DMA-able.
> + * @proto:	SPI protocol to use for the register operation.
> + *
> + * Return: zero on success, -errno otherwise
> + */
> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
> +		     enum spi_nor_protocol proto)
> +{
> +	if (!nor->spimem)
> +		return -EOPNOTSUPP;
> +
> +	spi_nor_spimem_setup_op(nor, op, proto);
> +	return spi_nor_spimem_exec_op(nor, op);
> +}
> +
> +/**
> + * spi_nor_write_reg() - write register to flash memory
> + * @nor:        pointer to 'struct spi_nor'
> + * @op:		SPI memory operation. op->data.buf must be DMA-able.
> + * @proto:	SPI protocol to use for the register operation.
> + *
> + * Return: zero on success, -errno otherwise
> + */
> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
> +		      enum spi_nor_protocol proto)
> +{
> +	int ret;
> +
> +	if (!nor->spimem)
> +		return -EOPNOTSUPP;
> +
> +	ret = spi_nor_write_enable(nor);
> +	if (ret)
> +		return ret;
> +	spi_nor_spimem_setup_op(nor, op, proto);
> +	return spi_nor_spimem_exec_op(nor, op);
> +}
> +
>  /**
>   * spi_nor_write_enable() - Set write enable latch with Write Enable 
> command.
>   * @nor:	pointer to 'struct spi_nor'.
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index f952061d5c24..7c704475946d 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -554,6 +554,10 @@ 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_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
> +		     enum spi_nor_protocol proto);
> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
> +		      enum spi_nor_protocol proto);
>  int spi_nor_erase_sector(struct spi_nor *nor, u32 addr);
> 
>  int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t
> len, u8 *buf);

-- 
-michael

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

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

* Re: [PATCH v3 7/9] mtd: spi-nor: micron-st: Rework spi_nor_micron_octal_dtr_enable()
  2022-04-11  9:10   ` Tudor Ambarus
@ 2022-04-19 11:43     ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:43 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> Introduce template operation to remove code duplication.
> Split spi_nor_micron_octal_dtr_enable() in 
> spi_nor_micron_octal_dtr_en()
> and spi_nor_micron_octal_dtr_dis() as it no longer made sense to try to
> keep everything alltogether: too many "if (enable)" throughout the 
> code,
> which made the code difficult to follow. Add dev_dbg messages in case
> spi_nor_read_id() fails.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

There is now
micron_st_nor_octal_dtr_en()
micron_st_nor_octal_dtr_dis()
and
micron_st_nor_octal_dtr_enable()

Now what does what? :) Maybe we should rename that octal_dtr_enable
op. (Or use two?)

Reviewed-by: Michael Walle <michael@walle.cc>

> ---
> v3: collect R-b, update commit message, add dev_dbg message in case
> spi_nor_read_id() fails.
> 
>  drivers/mtd/spi-nor/micron-st.c | 111 +++++++++++++++++---------------
>  1 file changed, 60 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/micron-st.c 
> b/drivers/mtd/spi-nor/micron-st.c
> index 41b87868ecf9..a447762c0d78 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -28,75 +28,78 @@
>  #define FSR_P_ERR		BIT(4)	/* Program operation status */
>  #define FSR_PT_ERR		BIT(1)	/* Protection error bit */
> 
> -static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool 
> enable)
> +/* Micron ST SPI NOR flash operations. */
> +#define MICRON_ST_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 0),		\
> +		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
> +
> +static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>  	struct spi_mem_op op;
>  	u8 *buf = nor->bouncebuf;
>  	int ret;
> 
> -	if (enable) {
> -		/* Use 20 dummy cycles for memory array reads. */
> -		ret = spi_nor_write_enable(nor);
> -		if (ret)
> -			return ret;
> -
> -		*buf = 20;
> -		op = (struct spi_mem_op)
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
> -				   SPI_MEM_OP_ADDR(3, SPINOR_REG_MT_CFR1V, 1),
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, buf, 1));
> -
> -		ret = spi_mem_exec_op(nor->spimem, &op);
> -		if (ret)
> -			return ret;
> -
> -		ret = spi_nor_wait_till_ready(nor);
> -		if (ret)
> -			return ret;
> -	}
> +	/* Use 20 dummy cycles for memory array reads. */
> +	*buf = 20;
> +	op = (struct spi_mem_op)
> +		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR1V, 1, buf);
> +	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
> +	if (ret)
> +		return ret;
> +	ret = spi_nor_wait_till_ready(nor);
> +	if (ret)
> +		return ret;
> 
> -	ret = spi_nor_write_enable(nor);
> +	buf[0] = SPINOR_MT_OCT_DTR;
> +	op = (struct spi_mem_op)
> +		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR0V, 1, buf);
> +	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
>  	if (ret)
>  		return ret;
> 
> -	if (enable) {
> -		buf[0] = SPINOR_MT_OCT_DTR;
> -	} else {
> -		/*
> -		 * The register is 1-byte wide, but 1-byte transactions are not
> -		 * allowed in 8D-8D-8D mode. The next register is the dummy
> -		 * cycle configuration register. Since the transaction needs to
> -		 * be at least 2 bytes wide, set the next register to its
> -		 * default value. This also makes sense because the value was
> -		 * changed when enabling 8D-8D-8D mode, it should be reset when
> -		 * disabling.
> -		 */
> -		buf[0] = SPINOR_MT_EXSPI;
> -		buf[1] = SPINOR_REG_MT_CFR1V_DEF;
> +	/* Read flash ID to make sure the switch was successful. */
> +	ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling
> 8D-8D-8D mode\n", ret);
> +		return ret;
>  	}
> 
> -	op = (struct spi_mem_op)
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
> -			   SPI_MEM_OP_ADDR(enable ? 3 : 4,
> -					   SPINOR_REG_MT_CFR0V, 1),
> -			   SPI_MEM_OP_NO_DUMMY,
> -			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
> +	if (memcmp(buf, nor->info->id, nor->info->id_len))
> +		return -EINVAL;
> 
> -	if (!enable)
> -		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
> +	return 0;
> +}
> +
> +static int micron_st_nor_octal_dtr_dis(struct spi_nor *nor)
> +{
> +	struct spi_mem_op op;
> +	u8 *buf = nor->bouncebuf;
> +	int ret;
> 
> -	ret = spi_mem_exec_op(nor->spimem, &op);
> +	/*
> +	 * The register is 1-byte wide, but 1-byte transactions are not 
> allowed
> +	 * in 8D-8D-8D mode. The next register is the dummy cycle 
> configuration
> +	 * register. Since the transaction needs to be at least 2 bytes wide,
> +	 * set the next register to its default value. This also makes sense
> +	 * because the value was changed when enabling 8D-8D-8D mode, it 
> should
> +	 * be reset when disabling.
> +	 */
> +	buf[0] = SPINOR_MT_EXSPI;
> +	buf[1] = SPINOR_REG_MT_CFR1V_DEF;
> +	op = (struct spi_mem_op)
> +		MICRON_ST_NOR_WR_ANY_REG_OP(4, SPINOR_REG_MT_CFR0V, 2, buf);
> +	ret = spi_nor_write_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
>  	if (ret)
>  		return ret;
> 
>  	/* Read flash ID to make sure the switch was successful. */
> -	if (enable)
> -		ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
> -	else
> -		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
> -	if (ret)
> +	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling
> 8D-8D-8D mode\n", ret);
>  		return ret;
> +	}
> 
>  	if (memcmp(buf, nor->info->id, nor->info->id_len))
>  		return -EINVAL;
> @@ -104,6 +107,12 @@ static int micron_st_nor_octal_dtr_enable(struct
> spi_nor *nor, bool enable)
>  	return 0;
>  }
> 
> +static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool 
> enable)
> +{
> +	return enable ? micron_st_nor_octal_dtr_en(nor) :
> +			micron_st_nor_octal_dtr_dis(nor);
> +}
> +
>  static void mt35xu512aba_default_init(struct spi_nor *nor)
>  {
>  	nor->params->octal_dtr_enable = micron_st_nor_octal_dtr_enable;

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

* Re: [PATCH v3 7/9] mtd: spi-nor: micron-st: Rework spi_nor_micron_octal_dtr_enable()
@ 2022-04-19 11:43     ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:43 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> Introduce template operation to remove code duplication.
> Split spi_nor_micron_octal_dtr_enable() in 
> spi_nor_micron_octal_dtr_en()
> and spi_nor_micron_octal_dtr_dis() as it no longer made sense to try to
> keep everything alltogether: too many "if (enable)" throughout the 
> code,
> which made the code difficult to follow. Add dev_dbg messages in case
> spi_nor_read_id() fails.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

There is now
micron_st_nor_octal_dtr_en()
micron_st_nor_octal_dtr_dis()
and
micron_st_nor_octal_dtr_enable()

Now what does what? :) Maybe we should rename that octal_dtr_enable
op. (Or use two?)

Reviewed-by: Michael Walle <michael@walle.cc>

> ---
> v3: collect R-b, update commit message, add dev_dbg message in case
> spi_nor_read_id() fails.
> 
>  drivers/mtd/spi-nor/micron-st.c | 111 +++++++++++++++++---------------
>  1 file changed, 60 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/micron-st.c 
> b/drivers/mtd/spi-nor/micron-st.c
> index 41b87868ecf9..a447762c0d78 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -28,75 +28,78 @@
>  #define FSR_P_ERR		BIT(4)	/* Program operation status */
>  #define FSR_PT_ERR		BIT(1)	/* Protection error bit */
> 
> -static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool 
> enable)
> +/* Micron ST SPI NOR flash operations. */
> +#define MICRON_ST_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 0),		\
> +		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
> +
> +static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>  	struct spi_mem_op op;
>  	u8 *buf = nor->bouncebuf;
>  	int ret;
> 
> -	if (enable) {
> -		/* Use 20 dummy cycles for memory array reads. */
> -		ret = spi_nor_write_enable(nor);
> -		if (ret)
> -			return ret;
> -
> -		*buf = 20;
> -		op = (struct spi_mem_op)
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
> -				   SPI_MEM_OP_ADDR(3, SPINOR_REG_MT_CFR1V, 1),
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, buf, 1));
> -
> -		ret = spi_mem_exec_op(nor->spimem, &op);
> -		if (ret)
> -			return ret;
> -
> -		ret = spi_nor_wait_till_ready(nor);
> -		if (ret)
> -			return ret;
> -	}
> +	/* Use 20 dummy cycles for memory array reads. */
> +	*buf = 20;
> +	op = (struct spi_mem_op)
> +		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR1V, 1, buf);
> +	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
> +	if (ret)
> +		return ret;
> +	ret = spi_nor_wait_till_ready(nor);
> +	if (ret)
> +		return ret;
> 
> -	ret = spi_nor_write_enable(nor);
> +	buf[0] = SPINOR_MT_OCT_DTR;
> +	op = (struct spi_mem_op)
> +		MICRON_ST_NOR_WR_ANY_REG_OP(3, SPINOR_REG_MT_CFR0V, 1, buf);
> +	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
>  	if (ret)
>  		return ret;
> 
> -	if (enable) {
> -		buf[0] = SPINOR_MT_OCT_DTR;
> -	} else {
> -		/*
> -		 * The register is 1-byte wide, but 1-byte transactions are not
> -		 * allowed in 8D-8D-8D mode. The next register is the dummy
> -		 * cycle configuration register. Since the transaction needs to
> -		 * be at least 2 bytes wide, set the next register to its
> -		 * default value. This also makes sense because the value was
> -		 * changed when enabling 8D-8D-8D mode, it should be reset when
> -		 * disabling.
> -		 */
> -		buf[0] = SPINOR_MT_EXSPI;
> -		buf[1] = SPINOR_REG_MT_CFR1V_DEF;
> +	/* Read flash ID to make sure the switch was successful. */
> +	ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling
> 8D-8D-8D mode\n", ret);
> +		return ret;
>  	}
> 
> -	op = (struct spi_mem_op)
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_MT_WR_ANY_REG, 1),
> -			   SPI_MEM_OP_ADDR(enable ? 3 : 4,
> -					   SPINOR_REG_MT_CFR0V, 1),
> -			   SPI_MEM_OP_NO_DUMMY,
> -			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
> +	if (memcmp(buf, nor->info->id, nor->info->id_len))
> +		return -EINVAL;
> 
> -	if (!enable)
> -		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
> +	return 0;
> +}
> +
> +static int micron_st_nor_octal_dtr_dis(struct spi_nor *nor)
> +{
> +	struct spi_mem_op op;
> +	u8 *buf = nor->bouncebuf;
> +	int ret;
> 
> -	ret = spi_mem_exec_op(nor->spimem, &op);
> +	/*
> +	 * The register is 1-byte wide, but 1-byte transactions are not 
> allowed
> +	 * in 8D-8D-8D mode. The next register is the dummy cycle 
> configuration
> +	 * register. Since the transaction needs to be at least 2 bytes wide,
> +	 * set the next register to its default value. This also makes sense
> +	 * because the value was changed when enabling 8D-8D-8D mode, it 
> should
> +	 * be reset when disabling.
> +	 */
> +	buf[0] = SPINOR_MT_EXSPI;
> +	buf[1] = SPINOR_REG_MT_CFR1V_DEF;
> +	op = (struct spi_mem_op)
> +		MICRON_ST_NOR_WR_ANY_REG_OP(4, SPINOR_REG_MT_CFR0V, 2, buf);
> +	ret = spi_nor_write_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
>  	if (ret)
>  		return ret;
> 
>  	/* Read flash ID to make sure the switch was successful. */
> -	if (enable)
> -		ret = spi_nor_read_id(nor, 0, 8, buf, SNOR_PROTO_8_8_8_DTR);
> -	else
> -		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
> -	if (ret)
> +	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling
> 8D-8D-8D mode\n", ret);
>  		return ret;
> +	}
> 
>  	if (memcmp(buf, nor->info->id, nor->info->id_len))
>  		return -EINVAL;
> @@ -104,6 +107,12 @@ static int micron_st_nor_octal_dtr_enable(struct
> spi_nor *nor, bool enable)
>  	return 0;
>  }
> 
> +static int micron_st_nor_octal_dtr_enable(struct spi_nor *nor, bool 
> enable)
> +{
> +	return enable ? micron_st_nor_octal_dtr_en(nor) :
> +			micron_st_nor_octal_dtr_dis(nor);
> +}
> +
>  static void mt35xu512aba_default_init(struct spi_nor *nor)
>  {
>  	nor->params->octal_dtr_enable = micron_st_nor_octal_dtr_enable;

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

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

* Re: [PATCH v3 8/9] mtd: spi-nor: spansion: Rework spi_nor_cypress_octal_dtr_enable()
  2022-04-11  9:10   ` Tudor Ambarus
@ 2022-04-19 11:44     ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:44 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> Introduce template operation to remove code duplication.
> Split spi_nor_cypress_octal_dtr_enable() in
> spi_nor_cypress_octal_dtr_ena() spi_nor_cypress_octal_dtr_dis() as it 
> no
> longer made sense to try to keep everything alltogether: too many
> "if (enable)" throughout the code, which made the code difficult to 
> read.
> Add debug messages in case spi_nor_read_id() fails.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

Reviewed-by: Michael Walle <michael@walle.cc>

> ---
> v3: collect R-b, update commit message, add dev_dbg message in case
> spi_nor_read_id() fails.
> 
>  drivers/mtd/spi-nor/spansion.c | 128 ++++++++++++++++++---------------
>  1 file changed, 69 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/spansion.c 
> b/drivers/mtd/spi-nor/spansion.c
> index c5988312cc91..35d8edb515a3 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -23,87 +23,81 @@
>  #define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS	0
>  #define SPINOR_OP_CYPRESS_RD_FAST		0xee
> 
> -/**
> - * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress 
> flashes.
> - * @nor:		pointer to a 'struct spi_nor'
> - * @enable:              whether to enable or disable Octal DTR
> - *
> - * This also sets the memory access latency cycles to 24 to allow the 
> flash to
> - * run at up to 200MHz.
> - *
> - * Return: 0 on success, -errno otherwise.
> - */
> -static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool 
> enable)
> +/* Cypress SPI NOR flash operations. */
> +#define CYPRESS_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 0),		\
> +		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
> +
> +static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>  	struct spi_mem_op op;
>  	u8 *buf = nor->bouncebuf;
>  	int ret;
> 
> -	if (enable) {
> -		/* Use 24 dummy cycles for memory array reads. */
> -		ret = spi_nor_write_enable(nor);
> -		if (ret)
> -			return ret;
> +	/* Use 24 dummy cycles for memory array reads. */
> +	*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
> +	op = (struct spi_mem_op)
> +		CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR2V, 1, buf);
> 
> -		*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
> -		op = (struct spi_mem_op)
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
> -				   SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR2V,
> -						   1),
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, buf, 1));
> +	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
> +	if (ret)
> +		return ret;
> 
> -		ret = spi_mem_exec_op(nor->spimem, &op);
> -		if (ret)
> -			return ret;
> +	ret = spi_nor_wait_till_ready(nor);
> +	if (ret)
> +		return ret;
> 
> -		ret = spi_nor_wait_till_ready(nor);
> -		if (ret)
> -			return ret;
> +	nor->read_dummy = 24;
> 
> -		nor->read_dummy = 24;
> -	}
> +	/* Set the octal and DTR enable bits. */
> +	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
> +	op = (struct spi_mem_op)
> +		CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR5V, 1, buf);
> 
> -	/* Set/unset the octal and DTR enable bits. */
> -	ret = spi_nor_write_enable(nor);
> +	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
>  	if (ret)
>  		return ret;
> 
> -	if (enable) {
> -		buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
> -	} else {
> -		/*
> -		 * The register is 1-byte wide, but 1-byte transactions are not
> -		 * allowed in 8D-8D-8D mode. Since there is no register at the
> -		 * next location, just initialize the value to 0 and let the
> -		 * transaction go on.
> -		 */
> -		buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
> -		buf[1] = 0;
> +	/* Read flash ID to make sure the switch was successful. */
> +	ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling
> 8D-8D-8D mode\n", ret);
> +		return ret;
>  	}
> 
> -	op = (struct spi_mem_op)
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
> -			   SPI_MEM_OP_ADDR(enable ? 3 : 4,
> -					   SPINOR_REG_CYPRESS_CFR5V,
> -					   1),
> -			   SPI_MEM_OP_NO_DUMMY,
> -			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
> +	if (memcmp(buf, nor->info->id, nor->info->id_len))
> +		return -EINVAL;
> 
> -	if (!enable)
> -		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
> +	return 0;
> +}
> 
> -	ret = spi_mem_exec_op(nor->spimem, &op);
> +static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
> +{
> +	struct spi_mem_op op;
> +	u8 *buf = nor->bouncebuf;
> +	int ret;
> +
> +	/*
> +	 * The register is 1-byte wide, but 1-byte transactions are not 
> allowed
> +	 * in 8D-8D-8D mode. Since there is no register at the next location,
> +	 * just initialize the value to 0 and let the transaction go on.
> +	 */
> +	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
> +	buf[1] = 0;
> +	op = (struct spi_mem_op)
> +		CYPRESS_NOR_WR_ANY_REG_OP(4, SPINOR_REG_CYPRESS_CFR5V, 2, buf);
> +	ret = spi_nor_write_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
>  	if (ret)
>  		return ret;
> 
>  	/* Read flash ID to make sure the switch was successful. */
> -	if (enable)
> -		ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
> -	else
> -		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
> -	if (ret)
> +	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling
> 8D-8D-8D mode\n", ret);
>  		return ret;
> +	}
> 
>  	if (memcmp(buf, nor->info->id, nor->info->id_len))
>  		return -EINVAL;
> @@ -111,6 +105,22 @@ static int cypress_nor_octal_dtr_enable(struct
> spi_nor *nor, bool enable)
>  	return 0;
>  }
> 
> +/**
> + * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress 
> flashes.
> + * @nor:		pointer to a 'struct spi_nor'
> + * @enable:              whether to enable or disable Octal DTR
> + *
> + * This also sets the memory access latency cycles to 24 to allow the 
> flash to
> + * run at up to 200MHz.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool 
> enable)
> +{
> +	return enable ? cypress_nor_octal_dtr_en(nor) :
> +			cypress_nor_octal_dtr_dis(nor);
> +}
> +
>  static void s28hs512t_default_init(struct spi_nor *nor)
>  {
>  	nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable;

-- 
-michael

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

* Re: [PATCH v3 8/9] mtd: spi-nor: spansion: Rework spi_nor_cypress_octal_dtr_enable()
@ 2022-04-19 11:44     ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:44 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> Introduce template operation to remove code duplication.
> Split spi_nor_cypress_octal_dtr_enable() in
> spi_nor_cypress_octal_dtr_ena() spi_nor_cypress_octal_dtr_dis() as it 
> no
> longer made sense to try to keep everything alltogether: too many
> "if (enable)" throughout the code, which made the code difficult to 
> read.
> Add debug messages in case spi_nor_read_id() fails.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>

Reviewed-by: Michael Walle <michael@walle.cc>

> ---
> v3: collect R-b, update commit message, add dev_dbg message in case
> spi_nor_read_id() fails.
> 
>  drivers/mtd/spi-nor/spansion.c | 128 ++++++++++++++++++---------------
>  1 file changed, 69 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/spansion.c 
> b/drivers/mtd/spi-nor/spansion.c
> index c5988312cc91..35d8edb515a3 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -23,87 +23,81 @@
>  #define SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS	0
>  #define SPINOR_OP_CYPRESS_RD_FAST		0xee
> 
> -/**
> - * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress 
> flashes.
> - * @nor:		pointer to a 'struct spi_nor'
> - * @enable:              whether to enable or disable Octal DTR
> - *
> - * This also sets the memory access latency cycles to 24 to allow the 
> flash to
> - * run at up to 200MHz.
> - *
> - * Return: 0 on success, -errno otherwise.
> - */
> -static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool 
> enable)
> +/* Cypress SPI NOR flash operations. */
> +#define CYPRESS_NOR_WR_ANY_REG_OP(naddr, addr, ndata, buf)		\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 0),		\
> +		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
> +
> +static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>  	struct spi_mem_op op;
>  	u8 *buf = nor->bouncebuf;
>  	int ret;
> 
> -	if (enable) {
> -		/* Use 24 dummy cycles for memory array reads. */
> -		ret = spi_nor_write_enable(nor);
> -		if (ret)
> -			return ret;
> +	/* Use 24 dummy cycles for memory array reads. */
> +	*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
> +	op = (struct spi_mem_op)
> +		CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR2V, 1, buf);
> 
> -		*buf = SPINOR_REG_CYPRESS_CFR2V_MEMLAT_11_24;
> -		op = (struct spi_mem_op)
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
> -				   SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR2V,
> -						   1),
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, buf, 1));
> +	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
> +	if (ret)
> +		return ret;
> 
> -		ret = spi_mem_exec_op(nor->spimem, &op);
> -		if (ret)
> -			return ret;
> +	ret = spi_nor_wait_till_ready(nor);
> +	if (ret)
> +		return ret;
> 
> -		ret = spi_nor_wait_till_ready(nor);
> -		if (ret)
> -			return ret;
> +	nor->read_dummy = 24;
> 
> -		nor->read_dummy = 24;
> -	}
> +	/* Set the octal and DTR enable bits. */
> +	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
> +	op = (struct spi_mem_op)
> +		CYPRESS_NOR_WR_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR5V, 1, buf);
> 
> -	/* Set/unset the octal and DTR enable bits. */
> -	ret = spi_nor_write_enable(nor);
> +	ret = spi_nor_write_reg(nor, &op, nor->reg_proto);
>  	if (ret)
>  		return ret;
> 
> -	if (enable) {
> -		buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_EN;
> -	} else {
> -		/*
> -		 * The register is 1-byte wide, but 1-byte transactions are not
> -		 * allowed in 8D-8D-8D mode. Since there is no register at the
> -		 * next location, just initialize the value to 0 and let the
> -		 * transaction go on.
> -		 */
> -		buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
> -		buf[1] = 0;
> +	/* Read flash ID to make sure the switch was successful. */
> +	ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d reading JEDEC ID after enabling
> 8D-8D-8D mode\n", ret);
> +		return ret;
>  	}
> 
> -	op = (struct spi_mem_op)
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WR_ANY_REG, 1),
> -			   SPI_MEM_OP_ADDR(enable ? 3 : 4,
> -					   SPINOR_REG_CYPRESS_CFR5V,
> -					   1),
> -			   SPI_MEM_OP_NO_DUMMY,
> -			   SPI_MEM_OP_DATA_OUT(enable ? 1 : 2, buf, 1));
> +	if (memcmp(buf, nor->info->id, nor->info->id_len))
> +		return -EINVAL;
> 
> -	if (!enable)
> -		spi_nor_spimem_setup_op(nor, &op, SNOR_PROTO_8_8_8_DTR);
> +	return 0;
> +}
> 
> -	ret = spi_mem_exec_op(nor->spimem, &op);
> +static int cypress_nor_octal_dtr_dis(struct spi_nor *nor)
> +{
> +	struct spi_mem_op op;
> +	u8 *buf = nor->bouncebuf;
> +	int ret;
> +
> +	/*
> +	 * The register is 1-byte wide, but 1-byte transactions are not 
> allowed
> +	 * in 8D-8D-8D mode. Since there is no register at the next location,
> +	 * just initialize the value to 0 and let the transaction go on.
> +	 */
> +	buf[0] = SPINOR_REG_CYPRESS_CFR5V_OCT_DTR_DS;
> +	buf[1] = 0;
> +	op = (struct spi_mem_op)
> +		CYPRESS_NOR_WR_ANY_REG_OP(4, SPINOR_REG_CYPRESS_CFR5V, 2, buf);
> +	ret = spi_nor_write_reg(nor, &op, SNOR_PROTO_8_8_8_DTR);
>  	if (ret)
>  		return ret;
> 
>  	/* Read flash ID to make sure the switch was successful. */
> -	if (enable)
> -		ret = spi_nor_read_id(nor, 4, 3, buf, SNOR_PROTO_8_8_8_DTR);
> -	else
> -		ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
> -	if (ret)
> +	ret = spi_nor_read_id(nor, 0, 0, buf, SNOR_PROTO_1_1_1);
> +	if (ret) {
> +		dev_dbg(nor->dev, "error %d reading JEDEC ID after disabling
> 8D-8D-8D mode\n", ret);
>  		return ret;
> +	}
> 
>  	if (memcmp(buf, nor->info->id, nor->info->id_len))
>  		return -EINVAL;
> @@ -111,6 +105,22 @@ static int cypress_nor_octal_dtr_enable(struct
> spi_nor *nor, bool enable)
>  	return 0;
>  }
> 
> +/**
> + * cypress_nor_octal_dtr_enable() - Enable octal DTR on Cypress 
> flashes.
> + * @nor:		pointer to a 'struct spi_nor'
> + * @enable:              whether to enable or disable Octal DTR
> + *
> + * This also sets the memory access latency cycles to 24 to allow the 
> flash to
> + * run at up to 200MHz.
> + *
> + * Return: 0 on success, -errno otherwise.
> + */
> +static int cypress_nor_octal_dtr_enable(struct spi_nor *nor, bool 
> enable)
> +{
> +	return enable ? cypress_nor_octal_dtr_en(nor) :
> +			cypress_nor_octal_dtr_dis(nor);
> +}
> +
>  static void s28hs512t_default_init(struct spi_nor *nor)
>  {
>  	nor->params->octal_dtr_enable = cypress_nor_octal_dtr_enable;

-- 
-michael

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

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

* Re: [PATCH v3 9/9] mtd: spi-nor: Introduce templates for SPI NOR operations
  2022-04-11  9:10   ` Tudor Ambarus
@ 2022-04-19 11:45     ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:45 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> Clean the op declaration and hide the details of each op. With this it
> results a cleanner, easier to read code. No functional change expected.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

I haven't gone through all of it.

Acked-by: Michael Walle <michael@walle.cc>

> ---
> v3: new patch taken from, no changes
> https://lore.kernel.org/lkml/20220304093011.198173-1-tudor.ambarus@microchip.com/
> 
>  drivers/mtd/spi-nor/core.c      | 101 ++++++-------------------------
>  drivers/mtd/spi-nor/core.h      | 102 ++++++++++++++++++++++++++++++++
>  drivers/mtd/spi-nor/micron-st.c |  24 ++++----
>  drivers/mtd/spi-nor/spansion.c  |  26 +++++---
>  drivers/mtd/spi-nor/xilinx.c    |  12 ++--
>  5 files changed, 158 insertions(+), 107 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index 42794328d3b6..fe853532204c 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -359,11 +359,7 @@ int spi_nor_write_enable(struct spi_nor *nor)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_WREN_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -390,11 +386,7 @@ int spi_nor_write_disable(struct spi_nor *nor)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_WRDI_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -454,11 +446,7 @@ int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, sr, 0));
> +		struct spi_mem_op op = SPI_NOR_RDSR_OP(sr);
> 
>  		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
>  			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
> @@ -498,11 +486,7 @@ int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, cr, 0));
> +		struct spi_mem_op op = SPI_NOR_RDCR_OP(cr);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -531,14 +515,7 @@ int spi_nor_set_4byte_addr_mode(struct spi_nor
> *nor, bool enable)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(enable ?
> -						  SPINOR_OP_EN4B :
> -						  SPINOR_OP_EX4B,
> -						  0),
> -				  SPI_MEM_OP_NO_ADDR,
> -				  SPI_MEM_OP_NO_DUMMY,
> -				  SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_EN4B_EX4B_OP(enable);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -572,11 +549,7 @@ static int spansion_set_4byte_addr_mode(struct
> spi_nor *nor, bool enable)
>  	nor->bouncebuf[0] = enable << 7;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 0));
> +		struct spi_mem_op op = SPI_NOR_BRWR_OP(nor->bouncebuf);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -606,11 +579,7 @@ int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
>  	nor->bouncebuf[0] = ear;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 0));
> +		struct spi_mem_op op = SPI_NOR_WREAR_OP(nor->bouncebuf);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -721,11 +690,7 @@ int spi_nor_global_block_unlock(struct spi_nor 
> *nor)
>  		return ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_GBULK, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_GBULK_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -760,11 +725,7 @@ int spi_nor_write_sr(struct spi_nor *nor, const
> u8 *sr, size_t len)
>  		return ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(len, sr, 0));
> +		struct spi_mem_op op = SPI_NOR_WRSR_OP(sr, len);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -964,11 +925,7 @@ static int spi_nor_write_sr2(struct spi_nor *nor,
> const u8 *sr2)
>  		return ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, sr2, 0));
> +		struct spi_mem_op op = SPI_NOR_WRSR2_OP(sr2);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -1000,11 +957,7 @@ static int spi_nor_read_sr2(struct spi_nor *nor, 
> u8 *sr2)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, sr2, 0));
> +		struct spi_mem_op op = SPI_NOR_RDSR2_OP(sr2);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -1033,11 +986,7 @@ static int spi_nor_erase_chip(struct spi_nor 
> *nor)
>  	dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10));
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_CHIP_ERASE_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
> 
> @@ -1179,10 +1128,8 @@ int spi_nor_erase_sector(struct spi_nor *nor, 
> u32 addr)
> 
>  	if (nor->spimem) {
>  		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(nor->erase_opcode, 0),
> -				   SPI_MEM_OP_ADDR(nor->addr_width, addr, 0),
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +			SPI_NOR_SECTOR_ERASE_OP(nor->erase_opcode,
> +						nor->addr_width, addr);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
> 
> @@ -1978,10 +1925,7 @@ static int spi_nor_spimem_check_op(struct 
> spi_nor *nor,
>  static int spi_nor_spimem_check_readop(struct spi_nor *nor,
>  				       const struct spi_nor_read_command *read)
>  {
> -	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(read->opcode, 0),
> -					  SPI_MEM_OP_ADDR(3, 0, 0),
> -					  SPI_MEM_OP_DUMMY(1, 0),
> -					  SPI_MEM_OP_DATA_IN(2, NULL, 0));
> +	struct spi_mem_op op = SPI_NOR_READ_OP(read->opcode);
> 
>  	spi_nor_spimem_setup_op(nor, &op, read->proto);
> 
> @@ -2004,10 +1948,7 @@ static int spi_nor_spimem_check_readop(struct
> spi_nor *nor,
>  static int spi_nor_spimem_check_pp(struct spi_nor *nor,
>  				   const struct spi_nor_pp_command *pp)
>  {
> -	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(pp->opcode, 0),
> -					  SPI_MEM_OP_ADDR(3, 0, 0),
> -					  SPI_MEM_OP_NO_DUMMY,
> -					  SPI_MEM_OP_DATA_OUT(2, NULL, 0));
> +	struct spi_mem_op op = SPI_NOR_PP_OP(pp->opcode);
> 
>  	spi_nor_spimem_setup_op(nor, &op, pp->proto);
> 
> @@ -2831,10 +2772,7 @@ static void spi_nor_soft_reset(struct spi_nor 
> *nor)
>  	struct spi_mem_op op;
>  	int ret;
> 
> -	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 
> 0),
> -			SPI_MEM_OP_NO_DUMMY,
> -			SPI_MEM_OP_NO_ADDR,
> -			SPI_MEM_OP_NO_DATA);
> +	op = (struct spi_mem_op)SPINOR_SRSTEN_OP;
> 
>  	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -2844,10 +2782,7 @@ static void spi_nor_soft_reset(struct spi_nor 
> *nor)
>  		return;
>  	}
> 
> -	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRST, 0),
> -			SPI_MEM_OP_NO_DUMMY,
> -			SPI_MEM_OP_NO_ADDR,
> -			SPI_MEM_OP_NO_DATA);
> +	op = (struct spi_mem_op)SPINOR_SRST_OP;
> 
>  	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 7c704475946d..8b7e597fd38c 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -18,6 +18,108 @@
>  		   SPI_MEM_OP_DUMMY(ndummy, 0),				\
>  		   SPI_MEM_OP_DATA_IN(len, buf, 0))
> 
> +#define SPI_NOR_WREN_OP							\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_WRDI_OP							\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_RDSR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
> +#define SPI_NOR_WRSR_OP(buf, len)					\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(len, buf, 0))
> +
> +#define SPI_NOR_RDSR2_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +#define SPI_NOR_WRSR2_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +#define SPI_NOR_RDCR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
> +#define SPI_NOR_EN4B_EX4B_OP(enable)					\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, 
> 0),	\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_BRWR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +#define SPI_NOR_WREAR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +#define SPI_NOR_GBULK_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_GBULK, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_CHIP_ERASE_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),		\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_SECTOR_ERASE_OP(opcode, addr_width, addr)		\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
> +		   SPI_MEM_OP_ADDR(addr_width, addr, 0),		\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_READ_OP(opcode)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
> +		   SPI_MEM_OP_ADDR(3, 0, 0),				\
> +		   SPI_MEM_OP_DUMMY(1, 0),				\
> +		   SPI_MEM_OP_DATA_IN(2, NULL, 0))
> +
> +#define SPI_NOR_PP_OP(opcode)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
> +		   SPI_MEM_OP_ADDR(3, 0, 0),				\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(2, NULL, 0))
> +
> +#define SPINOR_SRSTEN_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPINOR_SRST_OP							\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRST, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
>  enum spi_nor_option_flags {
>  	SNOR_F_HAS_SR_TB	= BIT(0),
>  	SNOR_F_NO_OP_CHIP_ERASE	= BIT(1),
> diff --git a/drivers/mtd/spi-nor/micron-st.c 
> b/drivers/mtd/spi-nor/micron-st.c
> index a447762c0d78..26b9a1c2309d 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -35,6 +35,18 @@
>  		   SPI_MEM_OP_NO_DUMMY,					\
>  		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
> 
> +#define MICRON_ST_RDFSR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
> +#define MICRON_ST_CLFSR_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
>  static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>  	struct spi_mem_op op;
> @@ -324,11 +336,7 @@ static int micron_st_nor_read_fsr(struct spi_nor
> *nor, u8 *fsr)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, fsr, 0));
> +		struct spi_mem_op op = MICRON_ST_RDFSR_OP(fsr);
> 
>  		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
>  			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
> @@ -363,11 +371,7 @@ static void micron_st_nor_clear_fsr(struct spi_nor 
> *nor)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = MICRON_ST_CLFSR_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> diff --git a/drivers/mtd/spi-nor/spansion.c 
> b/drivers/mtd/spi-nor/spansion.c
> index 35d8edb515a3..952db7af6932 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -30,6 +30,18 @@
>  		   SPI_MEM_OP_NO_DUMMY,					\
>  		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
> 
> +#define CYPRESS_NOR_RD_ANY_REG_OP(naddr, addr, buf)			\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0),		\
> +		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
> +#define SPANSION_CLSR_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
>  static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>  	struct spi_mem_op op;
> @@ -165,12 +177,12 @@ static int s28hs512t_post_bfpt_fixup(struct 
> spi_nor *nor,
>  	 * CFR3V[4] and set the correct size.
>  	 */
>  	struct spi_mem_op op =
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1),
> -			   SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR3V, 1),
> -			   SPI_MEM_OP_NO_DUMMY,
> -			   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
> +		CYPRESS_NOR_RD_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR3V,
> +					  nor->bouncebuf);
>  	int ret;
> 
> +	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> +
>  	ret = spi_mem_exec_op(nor->spimem, &op);
>  	if (ret)
>  		return ret;
> @@ -320,11 +332,7 @@ static void spansion_nor_clear_sr(struct spi_nor 
> *nor)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPANSION_CLSR_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> diff --git a/drivers/mtd/spi-nor/xilinx.c 
> b/drivers/mtd/spi-nor/xilinx.c
> index 9459ac2609dc..1d2f5db047bd 100644
> --- a/drivers/mtd/spi-nor/xilinx.c
> +++ b/drivers/mtd/spi-nor/xilinx.c
> @@ -15,6 +15,12 @@
>  #define XSR_PAGESIZE		BIT(0)	/* Page size in Po2 or Linear */
>  #define XSR_RDY			BIT(7)	/* Ready */
> 
> +#define XILINX_RDSR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
>  #define S3AN_INFO(_jedec_id, _n_sectors, _page_size)			\
>  		.id = {							\
>  			((_jedec_id) >> 16) & 0xff,			\
> @@ -72,11 +78,7 @@ static int xilinx_nor_read_sr(struct spi_nor *nor, 
> u8 *sr)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, sr, 0));
> +		struct spi_mem_op op = XILINX_RDSR_OP(sr);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);

-- 
-michael

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

* Re: [PATCH v3 9/9] mtd: spi-nor: Introduce templates for SPI NOR operations
@ 2022-04-19 11:45     ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:45 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> Clean the op declaration and hide the details of each op. With this it
> results a cleanner, easier to read code. No functional change expected.
> 
> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>

I haven't gone through all of it.

Acked-by: Michael Walle <michael@walle.cc>

> ---
> v3: new patch taken from, no changes
> https://lore.kernel.org/lkml/20220304093011.198173-1-tudor.ambarus@microchip.com/
> 
>  drivers/mtd/spi-nor/core.c      | 101 ++++++-------------------------
>  drivers/mtd/spi-nor/core.h      | 102 ++++++++++++++++++++++++++++++++
>  drivers/mtd/spi-nor/micron-st.c |  24 ++++----
>  drivers/mtd/spi-nor/spansion.c  |  26 +++++---
>  drivers/mtd/spi-nor/xilinx.c    |  12 ++--
>  5 files changed, 158 insertions(+), 107 deletions(-)
> 
> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> index 42794328d3b6..fe853532204c 100644
> --- a/drivers/mtd/spi-nor/core.c
> +++ b/drivers/mtd/spi-nor/core.c
> @@ -359,11 +359,7 @@ int spi_nor_write_enable(struct spi_nor *nor)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_WREN_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -390,11 +386,7 @@ int spi_nor_write_disable(struct spi_nor *nor)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_WRDI_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -454,11 +446,7 @@ int spi_nor_read_sr(struct spi_nor *nor, u8 *sr)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, sr, 0));
> +		struct spi_mem_op op = SPI_NOR_RDSR_OP(sr);
> 
>  		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
>  			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
> @@ -498,11 +486,7 @@ int spi_nor_read_cr(struct spi_nor *nor, u8 *cr)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, cr, 0));
> +		struct spi_mem_op op = SPI_NOR_RDCR_OP(cr);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -531,14 +515,7 @@ int spi_nor_set_4byte_addr_mode(struct spi_nor
> *nor, bool enable)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(enable ?
> -						  SPINOR_OP_EN4B :
> -						  SPINOR_OP_EX4B,
> -						  0),
> -				  SPI_MEM_OP_NO_ADDR,
> -				  SPI_MEM_OP_NO_DUMMY,
> -				  SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_EN4B_EX4B_OP(enable);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -572,11 +549,7 @@ static int spansion_set_4byte_addr_mode(struct
> spi_nor *nor, bool enable)
>  	nor->bouncebuf[0] = enable << 7;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 0));
> +		struct spi_mem_op op = SPI_NOR_BRWR_OP(nor->bouncebuf);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -606,11 +579,7 @@ int spi_nor_write_ear(struct spi_nor *nor, u8 ear)
>  	nor->bouncebuf[0] = ear;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, nor->bouncebuf, 0));
> +		struct spi_mem_op op = SPI_NOR_WREAR_OP(nor->bouncebuf);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -721,11 +690,7 @@ int spi_nor_global_block_unlock(struct spi_nor 
> *nor)
>  		return ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_GBULK, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_GBULK_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -760,11 +725,7 @@ int spi_nor_write_sr(struct spi_nor *nor, const
> u8 *sr, size_t len)
>  		return ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(len, sr, 0));
> +		struct spi_mem_op op = SPI_NOR_WRSR_OP(sr, len);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -964,11 +925,7 @@ static int spi_nor_write_sr2(struct spi_nor *nor,
> const u8 *sr2)
>  		return ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_OUT(1, sr2, 0));
> +		struct spi_mem_op op = SPI_NOR_WRSR2_OP(sr2);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -1000,11 +957,7 @@ static int spi_nor_read_sr2(struct spi_nor *nor, 
> u8 *sr2)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, sr2, 0));
> +		struct spi_mem_op op = SPI_NOR_RDSR2_OP(sr2);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -1033,11 +986,7 @@ static int spi_nor_erase_chip(struct spi_nor 
> *nor)
>  	dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd.size >> 10));
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPI_NOR_CHIP_ERASE_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
> 
> @@ -1179,10 +1128,8 @@ int spi_nor_erase_sector(struct spi_nor *nor, 
> u32 addr)
> 
>  	if (nor->spimem) {
>  		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(nor->erase_opcode, 0),
> -				   SPI_MEM_OP_ADDR(nor->addr_width, addr, 0),
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +			SPI_NOR_SECTOR_ERASE_OP(nor->erase_opcode,
> +						nor->addr_width, addr);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->write_proto);
> 
> @@ -1978,10 +1925,7 @@ static int spi_nor_spimem_check_op(struct 
> spi_nor *nor,
>  static int spi_nor_spimem_check_readop(struct spi_nor *nor,
>  				       const struct spi_nor_read_command *read)
>  {
> -	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(read->opcode, 0),
> -					  SPI_MEM_OP_ADDR(3, 0, 0),
> -					  SPI_MEM_OP_DUMMY(1, 0),
> -					  SPI_MEM_OP_DATA_IN(2, NULL, 0));
> +	struct spi_mem_op op = SPI_NOR_READ_OP(read->opcode);
> 
>  	spi_nor_spimem_setup_op(nor, &op, read->proto);
> 
> @@ -2004,10 +1948,7 @@ static int spi_nor_spimem_check_readop(struct
> spi_nor *nor,
>  static int spi_nor_spimem_check_pp(struct spi_nor *nor,
>  				   const struct spi_nor_pp_command *pp)
>  {
> -	struct spi_mem_op op = SPI_MEM_OP(SPI_MEM_OP_CMD(pp->opcode, 0),
> -					  SPI_MEM_OP_ADDR(3, 0, 0),
> -					  SPI_MEM_OP_NO_DUMMY,
> -					  SPI_MEM_OP_DATA_OUT(2, NULL, 0));
> +	struct spi_mem_op op = SPI_NOR_PP_OP(pp->opcode);
> 
>  	spi_nor_spimem_setup_op(nor, &op, pp->proto);
> 
> @@ -2831,10 +2772,7 @@ static void spi_nor_soft_reset(struct spi_nor 
> *nor)
>  	struct spi_mem_op op;
>  	int ret;
> 
> -	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 
> 0),
> -			SPI_MEM_OP_NO_DUMMY,
> -			SPI_MEM_OP_NO_ADDR,
> -			SPI_MEM_OP_NO_DATA);
> +	op = (struct spi_mem_op)SPINOR_SRSTEN_OP;
> 
>  	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> @@ -2844,10 +2782,7 @@ static void spi_nor_soft_reset(struct spi_nor 
> *nor)
>  		return;
>  	}
> 
> -	op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRST, 0),
> -			SPI_MEM_OP_NO_DUMMY,
> -			SPI_MEM_OP_NO_ADDR,
> -			SPI_MEM_OP_NO_DATA);
> +	op = (struct spi_mem_op)SPINOR_SRST_OP;
> 
>  	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
> index 7c704475946d..8b7e597fd38c 100644
> --- a/drivers/mtd/spi-nor/core.h
> +++ b/drivers/mtd/spi-nor/core.h
> @@ -18,6 +18,108 @@
>  		   SPI_MEM_OP_DUMMY(ndummy, 0),				\
>  		   SPI_MEM_OP_DATA_IN(len, buf, 0))
> 
> +#define SPI_NOR_WREN_OP							\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREN, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_WRDI_OP							\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRDI, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_RDSR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
> +#define SPI_NOR_WRSR_OP(buf, len)					\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(len, buf, 0))
> +
> +#define SPI_NOR_RDSR2_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDSR2, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +#define SPI_NOR_WRSR2_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WRSR2, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +#define SPI_NOR_RDCR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDCR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
> +#define SPI_NOR_EN4B_EX4B_OP(enable)					\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B, 
> 0),	\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_BRWR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_BRWR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +#define SPI_NOR_WREAR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_WREAR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(1, buf, 0))
> +
> +#define SPI_NOR_GBULK_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_GBULK, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_CHIP_ERASE_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CHIP_ERASE, 0),		\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_SECTOR_ERASE_OP(opcode, addr_width, addr)		\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
> +		   SPI_MEM_OP_ADDR(addr_width, addr, 0),		\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPI_NOR_READ_OP(opcode)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
> +		   SPI_MEM_OP_ADDR(3, 0, 0),				\
> +		   SPI_MEM_OP_DUMMY(1, 0),				\
> +		   SPI_MEM_OP_DATA_IN(2, NULL, 0))
> +
> +#define SPI_NOR_PP_OP(opcode)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(opcode, 0),				\
> +		   SPI_MEM_OP_ADDR(3, 0, 0),				\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_OUT(2, NULL, 0))
> +
> +#define SPINOR_SRSTEN_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRSTEN, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
> +#define SPINOR_SRST_OP							\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_SRST, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
>  enum spi_nor_option_flags {
>  	SNOR_F_HAS_SR_TB	= BIT(0),
>  	SNOR_F_NO_OP_CHIP_ERASE	= BIT(1),
> diff --git a/drivers/mtd/spi-nor/micron-st.c 
> b/drivers/mtd/spi-nor/micron-st.c
> index a447762c0d78..26b9a1c2309d 100644
> --- a/drivers/mtd/spi-nor/micron-st.c
> +++ b/drivers/mtd/spi-nor/micron-st.c
> @@ -35,6 +35,18 @@
>  		   SPI_MEM_OP_NO_DUMMY,					\
>  		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
> 
> +#define MICRON_ST_RDFSR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
> +#define MICRON_ST_CLFSR_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
>  static int micron_st_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>  	struct spi_mem_op op;
> @@ -324,11 +336,7 @@ static int micron_st_nor_read_fsr(struct spi_nor
> *nor, u8 *fsr)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RDFSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, fsr, 0));
> +		struct spi_mem_op op = MICRON_ST_RDFSR_OP(fsr);
> 
>  		if (nor->reg_proto == SNOR_PROTO_8_8_8_DTR) {
>  			op.addr.nbytes = nor->params->rdsr_addr_nbytes;
> @@ -363,11 +371,7 @@ static void micron_st_nor_clear_fsr(struct spi_nor 
> *nor)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLFSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = MICRON_ST_CLFSR_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> diff --git a/drivers/mtd/spi-nor/spansion.c 
> b/drivers/mtd/spi-nor/spansion.c
> index 35d8edb515a3..952db7af6932 100644
> --- a/drivers/mtd/spi-nor/spansion.c
> +++ b/drivers/mtd/spi-nor/spansion.c
> @@ -30,6 +30,18 @@
>  		   SPI_MEM_OP_NO_DUMMY,					\
>  		   SPI_MEM_OP_DATA_OUT(ndata, buf, 0))
> 
> +#define CYPRESS_NOR_RD_ANY_REG_OP(naddr, addr, buf)			\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 0),		\
> +		   SPI_MEM_OP_ADDR(naddr, addr, 0),			\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
> +#define SPANSION_CLSR_OP						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_NO_DATA)
> +
>  static int cypress_nor_octal_dtr_en(struct spi_nor *nor)
>  {
>  	struct spi_mem_op op;
> @@ -165,12 +177,12 @@ static int s28hs512t_post_bfpt_fixup(struct 
> spi_nor *nor,
>  	 * CFR3V[4] and set the correct size.
>  	 */
>  	struct spi_mem_op op =
> -		SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_RD_ANY_REG, 1),
> -			   SPI_MEM_OP_ADDR(3, SPINOR_REG_CYPRESS_CFR3V, 1),
> -			   SPI_MEM_OP_NO_DUMMY,
> -			   SPI_MEM_OP_DATA_IN(1, nor->bouncebuf, 1));
> +		CYPRESS_NOR_RD_ANY_REG_OP(3, SPINOR_REG_CYPRESS_CFR3V,
> +					  nor->bouncebuf);
>  	int ret;
> 
> +	spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> +
>  	ret = spi_mem_exec_op(nor->spimem, &op);
>  	if (ret)
>  		return ret;
> @@ -320,11 +332,7 @@ static void spansion_nor_clear_sr(struct spi_nor 
> *nor)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(SPINOR_OP_CLSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_NO_DATA);
> +		struct spi_mem_op op = SPANSION_CLSR_OP;
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);
> 
> diff --git a/drivers/mtd/spi-nor/xilinx.c 
> b/drivers/mtd/spi-nor/xilinx.c
> index 9459ac2609dc..1d2f5db047bd 100644
> --- a/drivers/mtd/spi-nor/xilinx.c
> +++ b/drivers/mtd/spi-nor/xilinx.c
> @@ -15,6 +15,12 @@
>  #define XSR_PAGESIZE		BIT(0)	/* Page size in Po2 or Linear */
>  #define XSR_RDY			BIT(7)	/* Ready */
> 
> +#define XILINX_RDSR_OP(buf)						\
> +	SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),			\
> +		   SPI_MEM_OP_NO_ADDR,					\
> +		   SPI_MEM_OP_NO_DUMMY,					\
> +		   SPI_MEM_OP_DATA_IN(1, buf, 0))
> +
>  #define S3AN_INFO(_jedec_id, _n_sectors, _page_size)			\
>  		.id = {							\
>  			((_jedec_id) >> 16) & 0xff,			\
> @@ -72,11 +78,7 @@ static int xilinx_nor_read_sr(struct spi_nor *nor, 
> u8 *sr)
>  	int ret;
> 
>  	if (nor->spimem) {
> -		struct spi_mem_op op =
> -			SPI_MEM_OP(SPI_MEM_OP_CMD(XILINX_OP_RDSR, 0),
> -				   SPI_MEM_OP_NO_ADDR,
> -				   SPI_MEM_OP_NO_DUMMY,
> -				   SPI_MEM_OP_DATA_IN(1, sr, 0));
> +		struct spi_mem_op op = XILINX_RDSR_OP(sr);
> 
>  		spi_nor_spimem_setup_op(nor, &op, nor->reg_proto);

-- 
-michael

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-19 11:19     ` Michael Walle
@ 2022-04-19 11:46       ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:46 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre, Takahiro Kuwano

Am 2022-04-19 13:19, schrieb Michael Walle:
> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>> There are manufacturers that use registers indexed by address. Some of
>> them support "read/write any register" opcodes. Provide core methods 
>> that
>> can be used by all manufacturers. SPI NOR controller ops are 
>> intentionally
>> not supported as we intend to move all the SPI NOR controller drivers
>> under the SPI subsystem.
>> 
>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
> 
> I still don't like it because the function doesn't do
> anything what the function name might suggest. The read
> just executes an op, the write executes an op with a
> write enable before. All the behavior is determined by the
> 'op' argument.
> 
> Anyway,
> Reviewed-by: Michael Walle <michael@walle.cc>
> 
>> ---
>> v3: no changes
>> 
>>  drivers/mtd/spi-nor/core.c | 41 
>> ++++++++++++++++++++++++++++++++++++++
>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>  2 files changed, 45 insertions(+)
>> 
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 6165dc7bfd17..42794328d3b6 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>> loff_t to, size_t len,
>>  	return nor->controller_ops->write(nor, to, len, buf);
>>  }
>> 
>> +/**
>> + * spi_nor_read_reg() - read register to flash memory
>> + * @nor:        pointer to 'struct spi_nor'.
>> + * @op:		SPI memory operation. op->data.buf must be DMA-able.
>> + * @proto:	SPI protocol to use for the register operation.
>> + *
>> + * Return: zero on success, -errno otherwise
>> + */
>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +		     enum spi_nor_protocol proto)
>> +{
>> +	if (!nor->spimem)
>> +		return -EOPNOTSUPP;
>> +
>> +	spi_nor_spimem_setup_op(nor, op, proto);
>> +	return spi_nor_spimem_exec_op(nor, op);
>> +}
>> +
>> +/**
>> + * spi_nor_write_reg() - write register to flash memory
>> + * @nor:        pointer to 'struct spi_nor'
>> + * @op:		SPI memory operation. op->data.buf must be DMA-able.
>> + * @proto:	SPI protocol to use for the register operation.
>> + *
>> + * Return: zero on success, -errno otherwise
>> + */
>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +		      enum spi_nor_protocol proto)
>> +{
>> +	int ret;
>> +
>> +	if (!nor->spimem)
>> +		return -EOPNOTSUPP;
>> +
>> +	ret = spi_nor_write_enable(nor);
>> +	if (ret)
>> +		return ret;
>> +	spi_nor_spimem_setup_op(nor, op, proto);
>> +	return spi_nor_spimem_exec_op(nor, op);

After seeing your next two patches. Shouldn't the
spi_nor_wait_until_ready() call be here too?

-michael

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-19 11:46       ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 11:46 UTC (permalink / raw)
  To: Tudor Ambarus
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre, Takahiro Kuwano

Am 2022-04-19 13:19, schrieb Michael Walle:
> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>> There are manufacturers that use registers indexed by address. Some of
>> them support "read/write any register" opcodes. Provide core methods 
>> that
>> can be used by all manufacturers. SPI NOR controller ops are 
>> intentionally
>> not supported as we intend to move all the SPI NOR controller drivers
>> under the SPI subsystem.
>> 
>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
> 
> I still don't like it because the function doesn't do
> anything what the function name might suggest. The read
> just executes an op, the write executes an op with a
> write enable before. All the behavior is determined by the
> 'op' argument.
> 
> Anyway,
> Reviewed-by: Michael Walle <michael@walle.cc>
> 
>> ---
>> v3: no changes
>> 
>>  drivers/mtd/spi-nor/core.c | 41 
>> ++++++++++++++++++++++++++++++++++++++
>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>  2 files changed, 45 insertions(+)
>> 
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 6165dc7bfd17..42794328d3b6 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>> loff_t to, size_t len,
>>  	return nor->controller_ops->write(nor, to, len, buf);
>>  }
>> 
>> +/**
>> + * spi_nor_read_reg() - read register to flash memory
>> + * @nor:        pointer to 'struct spi_nor'.
>> + * @op:		SPI memory operation. op->data.buf must be DMA-able.
>> + * @proto:	SPI protocol to use for the register operation.
>> + *
>> + * Return: zero on success, -errno otherwise
>> + */
>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +		     enum spi_nor_protocol proto)
>> +{
>> +	if (!nor->spimem)
>> +		return -EOPNOTSUPP;
>> +
>> +	spi_nor_spimem_setup_op(nor, op, proto);
>> +	return spi_nor_spimem_exec_op(nor, op);
>> +}
>> +
>> +/**
>> + * spi_nor_write_reg() - write register to flash memory
>> + * @nor:        pointer to 'struct spi_nor'
>> + * @op:		SPI memory operation. op->data.buf must be DMA-able.
>> + * @proto:	SPI protocol to use for the register operation.
>> + *
>> + * Return: zero on success, -errno otherwise
>> + */
>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +		      enum spi_nor_protocol proto)
>> +{
>> +	int ret;
>> +
>> +	if (!nor->spimem)
>> +		return -EOPNOTSUPP;
>> +
>> +	ret = spi_nor_write_enable(nor);
>> +	if (ret)
>> +		return ret;
>> +	spi_nor_spimem_setup_op(nor, op, proto);
>> +	return spi_nor_spimem_exec_op(nor, op);

After seeing your next two patches. Shouldn't the
spi_nor_wait_until_ready() call be here too?

-michael

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-19 11:46       ` Michael Walle
@ 2022-04-19 12:08         ` Tudor.Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-19 12:08 UTC (permalink / raw)
  To: michael
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 4/19/22 14:46, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2022-04-19 13:19, schrieb Michael Walle:
>> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>> There are manufacturers that use registers indexed by address. Some of
>>> them support "read/write any register" opcodes. Provide core methods
>>> that
>>> can be used by all manufacturers. SPI NOR controller ops are
>>> intentionally
>>> not supported as we intend to move all the SPI NOR controller drivers
>>> under the SPI subsystem.
>>>
>>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>
>> I still don't like it because the function doesn't do
>> anything what the function name might suggest. The read
>> just executes an op, the write executes an op with a
>> write enable before. All the behavior is determined by the
>> 'op' argument.
>>
>> Anyway,
>> Reviewed-by: Michael Walle <michael@walle.cc>
>>
>>> ---
>>> v3: no changes
>>>
>>>  drivers/mtd/spi-nor/core.c | 41
>>> ++++++++++++++++++++++++++++++++++++++
>>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>>  2 files changed, 45 insertions(+)
>>>
>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>> index 6165dc7bfd17..42794328d3b6 100644
>>> --- a/drivers/mtd/spi-nor/core.c
>>> +++ b/drivers/mtd/spi-nor/core.c
>>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>> loff_t to, size_t len,
>>>      return nor->controller_ops->write(nor, to, len, buf);
>>>  }
>>>
>>> +/**
>>> + * spi_nor_read_reg() - read register to flash memory
>>> + * @nor:        pointer to 'struct spi_nor'.
>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>> + * @proto:  SPI protocol to use for the register operation.
>>> + *
>>> + * Return: zero on success, -errno otherwise
>>> + */
>>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>> +                 enum spi_nor_protocol proto)
>>> +{
>>> +    if (!nor->spimem)
>>> +            return -EOPNOTSUPP;
>>> +
>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>> +    return spi_nor_spimem_exec_op(nor, op);
>>> +}
>>> +
>>> +/**
>>> + * spi_nor_write_reg() - write register to flash memory
>>> + * @nor:        pointer to 'struct spi_nor'
>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>> + * @proto:  SPI protocol to use for the register operation.
>>> + *
>>> + * Return: zero on success, -errno otherwise
>>> + */
>>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>> +                  enum spi_nor_protocol proto)
>>> +{
>>> +    int ret;
>>> +
>>> +    if (!nor->spimem)
>>> +            return -EOPNOTSUPP;
>>> +
>>> +    ret = spi_nor_write_enable(nor);
>>> +    if (ret)
>>> +            return ret;
>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>> +    return spi_nor_spimem_exec_op(nor, op);
> 
> After seeing your next two patches. Shouldn't the
> spi_nor_wait_until_ready() call be here too?
> 

I thought of this too, but seems that for a reason that I don't
remember, we don't call for spi_nor_wait_until_ready after we
write the octal DTR bit. Pratyush, do you remember why?

Thanks,
ta

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-19 12:08         ` Tudor.Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-19 12:08 UTC (permalink / raw)
  To: michael
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 4/19/22 14:46, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2022-04-19 13:19, schrieb Michael Walle:
>> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>> There are manufacturers that use registers indexed by address. Some of
>>> them support "read/write any register" opcodes. Provide core methods
>>> that
>>> can be used by all manufacturers. SPI NOR controller ops are
>>> intentionally
>>> not supported as we intend to move all the SPI NOR controller drivers
>>> under the SPI subsystem.
>>>
>>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>
>> I still don't like it because the function doesn't do
>> anything what the function name might suggest. The read
>> just executes an op, the write executes an op with a
>> write enable before. All the behavior is determined by the
>> 'op' argument.
>>
>> Anyway,
>> Reviewed-by: Michael Walle <michael@walle.cc>
>>
>>> ---
>>> v3: no changes
>>>
>>>  drivers/mtd/spi-nor/core.c | 41
>>> ++++++++++++++++++++++++++++++++++++++
>>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>>  2 files changed, 45 insertions(+)
>>>
>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>> index 6165dc7bfd17..42794328d3b6 100644
>>> --- a/drivers/mtd/spi-nor/core.c
>>> +++ b/drivers/mtd/spi-nor/core.c
>>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>> loff_t to, size_t len,
>>>      return nor->controller_ops->write(nor, to, len, buf);
>>>  }
>>>
>>> +/**
>>> + * spi_nor_read_reg() - read register to flash memory
>>> + * @nor:        pointer to 'struct spi_nor'.
>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>> + * @proto:  SPI protocol to use for the register operation.
>>> + *
>>> + * Return: zero on success, -errno otherwise
>>> + */
>>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>> +                 enum spi_nor_protocol proto)
>>> +{
>>> +    if (!nor->spimem)
>>> +            return -EOPNOTSUPP;
>>> +
>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>> +    return spi_nor_spimem_exec_op(nor, op);
>>> +}
>>> +
>>> +/**
>>> + * spi_nor_write_reg() - write register to flash memory
>>> + * @nor:        pointer to 'struct spi_nor'
>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>> + * @proto:  SPI protocol to use for the register operation.
>>> + *
>>> + * Return: zero on success, -errno otherwise
>>> + */
>>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>> +                  enum spi_nor_protocol proto)
>>> +{
>>> +    int ret;
>>> +
>>> +    if (!nor->spimem)
>>> +            return -EOPNOTSUPP;
>>> +
>>> +    ret = spi_nor_write_enable(nor);
>>> +    if (ret)
>>> +            return ret;
>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>> +    return spi_nor_spimem_exec_op(nor, op);
> 
> After seeing your next two patches. Shouldn't the
> spi_nor_wait_until_ready() call be here too?
> 

I thought of this too, but seems that for a reason that I don't
remember, we don't call for spi_nor_wait_until_ready after we
write the octal DTR bit. Pratyush, do you remember why?

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-19 12:08         ` Tudor.Ambarus
@ 2022-04-19 12:32           ` Pratyush Yadav
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Yadav @ 2022-04-19 12:32 UTC (permalink / raw)
  To: Tudor.Ambarus
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
> On 4/19/22 14:46, Michael Walle wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > Am 2022-04-19 13:19, schrieb Michael Walle:
> >> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> >>> There are manufacturers that use registers indexed by address. Some of
> >>> them support "read/write any register" opcodes. Provide core methods
> >>> that
> >>> can be used by all manufacturers. SPI NOR controller ops are
> >>> intentionally
> >>> not supported as we intend to move all the SPI NOR controller drivers
> >>> under the SPI subsystem.
> >>>
> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> >>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> >>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
> >>
> >> I still don't like it because the function doesn't do
> >> anything what the function name might suggest. The read
> >> just executes an op, the write executes an op with a
> >> write enable before. All the behavior is determined by the
> >> 'op' argument.
> >>
> >> Anyway,
> >> Reviewed-by: Michael Walle <michael@walle.cc>
> >>
> >>> ---
> >>> v3: no changes
> >>>
> >>>  drivers/mtd/spi-nor/core.c | 41
> >>> ++++++++++++++++++++++++++++++++++++++
> >>>  drivers/mtd/spi-nor/core.h |  4 ++++
> >>>  2 files changed, 45 insertions(+)
> >>>
> >>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> >>> index 6165dc7bfd17..42794328d3b6 100644
> >>> --- a/drivers/mtd/spi-nor/core.c
> >>> +++ b/drivers/mtd/spi-nor/core.c
> >>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
> >>> loff_t to, size_t len,
> >>>      return nor->controller_ops->write(nor, to, len, buf);
> >>>  }
> >>>
> >>> +/**
> >>> + * spi_nor_read_reg() - read register to flash memory
> >>> + * @nor:        pointer to 'struct spi_nor'.
> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
> >>> + * @proto:  SPI protocol to use for the register operation.
> >>> + *
> >>> + * Return: zero on success, -errno otherwise
> >>> + */
> >>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
> >>> +                 enum spi_nor_protocol proto)
> >>> +{
> >>> +    if (!nor->spimem)
> >>> +            return -EOPNOTSUPP;
> >>> +
> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
> >>> +    return spi_nor_spimem_exec_op(nor, op);
> >>> +}
> >>> +
> >>> +/**
> >>> + * spi_nor_write_reg() - write register to flash memory
> >>> + * @nor:        pointer to 'struct spi_nor'
> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
> >>> + * @proto:  SPI protocol to use for the register operation.
> >>> + *
> >>> + * Return: zero on success, -errno otherwise
> >>> + */
> >>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
> >>> +                  enum spi_nor_protocol proto)
> >>> +{
> >>> +    int ret;
> >>> +
> >>> +    if (!nor->spimem)
> >>> +            return -EOPNOTSUPP;
> >>> +
> >>> +    ret = spi_nor_write_enable(nor);
> >>> +    if (ret)
> >>> +            return ret;
> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
> >>> +    return spi_nor_spimem_exec_op(nor, op);
> > 
> > After seeing your next two patches. Shouldn't the
> > spi_nor_wait_until_ready() call be here too?
> > 
> 
> I thought of this too, but seems that for a reason that I don't
> remember, we don't call for spi_nor_wait_until_ready after we
> write the octal DTR bit. Pratyush, do you remember why?

We are not sure the protocol changed correctly so we can't rely on 
spi_nor_wait_until_ready(). We read the ID instead to be sure.

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-19 12:32           ` Pratyush Yadav
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Yadav @ 2022-04-19 12:32 UTC (permalink / raw)
  To: Tudor.Ambarus
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
> On 4/19/22 14:46, Michael Walle wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > Am 2022-04-19 13:19, schrieb Michael Walle:
> >> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> >>> There are manufacturers that use registers indexed by address. Some of
> >>> them support "read/write any register" opcodes. Provide core methods
> >>> that
> >>> can be used by all manufacturers. SPI NOR controller ops are
> >>> intentionally
> >>> not supported as we intend to move all the SPI NOR controller drivers
> >>> under the SPI subsystem.
> >>>
> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> >>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> >>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
> >>
> >> I still don't like it because the function doesn't do
> >> anything what the function name might suggest. The read
> >> just executes an op, the write executes an op with a
> >> write enable before. All the behavior is determined by the
> >> 'op' argument.
> >>
> >> Anyway,
> >> Reviewed-by: Michael Walle <michael@walle.cc>
> >>
> >>> ---
> >>> v3: no changes
> >>>
> >>>  drivers/mtd/spi-nor/core.c | 41
> >>> ++++++++++++++++++++++++++++++++++++++
> >>>  drivers/mtd/spi-nor/core.h |  4 ++++
> >>>  2 files changed, 45 insertions(+)
> >>>
> >>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> >>> index 6165dc7bfd17..42794328d3b6 100644
> >>> --- a/drivers/mtd/spi-nor/core.c
> >>> +++ b/drivers/mtd/spi-nor/core.c
> >>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
> >>> loff_t to, size_t len,
> >>>      return nor->controller_ops->write(nor, to, len, buf);
> >>>  }
> >>>
> >>> +/**
> >>> + * spi_nor_read_reg() - read register to flash memory
> >>> + * @nor:        pointer to 'struct spi_nor'.
> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
> >>> + * @proto:  SPI protocol to use for the register operation.
> >>> + *
> >>> + * Return: zero on success, -errno otherwise
> >>> + */
> >>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
> >>> +                 enum spi_nor_protocol proto)
> >>> +{
> >>> +    if (!nor->spimem)
> >>> +            return -EOPNOTSUPP;
> >>> +
> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
> >>> +    return spi_nor_spimem_exec_op(nor, op);
> >>> +}
> >>> +
> >>> +/**
> >>> + * spi_nor_write_reg() - write register to flash memory
> >>> + * @nor:        pointer to 'struct spi_nor'
> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
> >>> + * @proto:  SPI protocol to use for the register operation.
> >>> + *
> >>> + * Return: zero on success, -errno otherwise
> >>> + */
> >>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
> >>> +                  enum spi_nor_protocol proto)
> >>> +{
> >>> +    int ret;
> >>> +
> >>> +    if (!nor->spimem)
> >>> +            return -EOPNOTSUPP;
> >>> +
> >>> +    ret = spi_nor_write_enable(nor);
> >>> +    if (ret)
> >>> +            return ret;
> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
> >>> +    return spi_nor_spimem_exec_op(nor, op);
> > 
> > After seeing your next two patches. Shouldn't the
> > spi_nor_wait_until_ready() call be here too?
> > 
> 
> I thought of this too, but seems that for a reason that I don't
> remember, we don't call for spi_nor_wait_until_ready after we
> write the octal DTR bit. Pratyush, do you remember why?

We are not sure the protocol changed correctly so we can't rely on 
spi_nor_wait_until_ready(). We read the ID instead to be sure.

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-19 12:32           ` Pratyush Yadav
@ 2022-04-19 12:46             ` Michael Walle
  -1 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 12:46 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Tudor.Ambarus, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

Am 2022-04-19 14:32, schrieb Pratyush Yadav:
> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>> On 4/19/22 14:46, Michael Walle wrote:
>> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>> >
>> > Am 2022-04-19 13:19, schrieb Michael Walle:
>> >> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>> >>> There are manufacturers that use registers indexed by address. Some of
>> >>> them support "read/write any register" opcodes. Provide core methods
>> >>> that
>> >>> can be used by all manufacturers. SPI NOR controller ops are
>> >>> intentionally
>> >>> not supported as we intend to move all the SPI NOR controller drivers
>> >>> under the SPI subsystem.
>> >>>
>> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>> >>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>> >>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>> >>
>> >> I still don't like it because the function doesn't do
>> >> anything what the function name might suggest. The read
>> >> just executes an op, the write executes an op with a
>> >> write enable before. All the behavior is determined by the
>> >> 'op' argument.
>> >>
>> >> Anyway,
>> >> Reviewed-by: Michael Walle <michael@walle.cc>
>> >>
>> >>> ---
>> >>> v3: no changes
>> >>>
>> >>>  drivers/mtd/spi-nor/core.c | 41
>> >>> ++++++++++++++++++++++++++++++++++++++
>> >>>  drivers/mtd/spi-nor/core.h |  4 ++++
>> >>>  2 files changed, 45 insertions(+)
>> >>>
>> >>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> >>> index 6165dc7bfd17..42794328d3b6 100644
>> >>> --- a/drivers/mtd/spi-nor/core.c
>> >>> +++ b/drivers/mtd/spi-nor/core.c
>> >>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>> >>> loff_t to, size_t len,
>> >>>      return nor->controller_ops->write(nor, to, len, buf);
>> >>>  }
>> >>>
>> >>> +/**
>> >>> + * spi_nor_read_reg() - read register to flash memory
>> >>> + * @nor:        pointer to 'struct spi_nor'.
>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>> >>> + * @proto:  SPI protocol to use for the register operation.
>> >>> + *
>> >>> + * Return: zero on success, -errno otherwise
>> >>> + */
>> >>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> >>> +                 enum spi_nor_protocol proto)
>> >>> +{
>> >>> +    if (!nor->spimem)
>> >>> +            return -EOPNOTSUPP;
>> >>> +
>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
>> >>> +    return spi_nor_spimem_exec_op(nor, op);
>> >>> +}
>> >>> +
>> >>> +/**
>> >>> + * spi_nor_write_reg() - write register to flash memory
>> >>> + * @nor:        pointer to 'struct spi_nor'
>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>> >>> + * @proto:  SPI protocol to use for the register operation.
>> >>> + *
>> >>> + * Return: zero on success, -errno otherwise
>> >>> + */
>> >>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> >>> +                  enum spi_nor_protocol proto)
>> >>> +{
>> >>> +    int ret;
>> >>> +
>> >>> +    if (!nor->spimem)
>> >>> +            return -EOPNOTSUPP;
>> >>> +
>> >>> +    ret = spi_nor_write_enable(nor);
>> >>> +    if (ret)
>> >>> +            return ret;
>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
>> >>> +    return spi_nor_spimem_exec_op(nor, op);
>> >
>> > After seeing your next two patches. Shouldn't the
>> > spi_nor_wait_until_ready() call be here too?
>> >
>> 
>> I thought of this too, but seems that for a reason that I don't
>> remember, we don't call for spi_nor_wait_until_ready after we
>> write the octal DTR bit. Pratyush, do you remember why?
> 
> We are not sure the protocol changed correctly so we can't rely on
> spi_nor_wait_until_ready(). We read the ID instead to be sure.

So besides the fact that the write_reg only works with the 'correct'
op parameter, it is also tailored to the special use case. For real
write_reg(), the user would actually has to poll the status bit
afterwards? :(

-michael

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-19 12:46             ` Michael Walle
  0 siblings, 0 replies; 56+ messages in thread
From: Michael Walle @ 2022-04-19 12:46 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Tudor.Ambarus, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

Am 2022-04-19 14:32, schrieb Pratyush Yadav:
> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>> On 4/19/22 14:46, Michael Walle wrote:
>> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>> >
>> > Am 2022-04-19 13:19, schrieb Michael Walle:
>> >> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>> >>> There are manufacturers that use registers indexed by address. Some of
>> >>> them support "read/write any register" opcodes. Provide core methods
>> >>> that
>> >>> can be used by all manufacturers. SPI NOR controller ops are
>> >>> intentionally
>> >>> not supported as we intend to move all the SPI NOR controller drivers
>> >>> under the SPI subsystem.
>> >>>
>> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>> >>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>> >>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>> >>
>> >> I still don't like it because the function doesn't do
>> >> anything what the function name might suggest. The read
>> >> just executes an op, the write executes an op with a
>> >> write enable before. All the behavior is determined by the
>> >> 'op' argument.
>> >>
>> >> Anyway,
>> >> Reviewed-by: Michael Walle <michael@walle.cc>
>> >>
>> >>> ---
>> >>> v3: no changes
>> >>>
>> >>>  drivers/mtd/spi-nor/core.c | 41
>> >>> ++++++++++++++++++++++++++++++++++++++
>> >>>  drivers/mtd/spi-nor/core.h |  4 ++++
>> >>>  2 files changed, 45 insertions(+)
>> >>>
>> >>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> >>> index 6165dc7bfd17..42794328d3b6 100644
>> >>> --- a/drivers/mtd/spi-nor/core.c
>> >>> +++ b/drivers/mtd/spi-nor/core.c
>> >>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>> >>> loff_t to, size_t len,
>> >>>      return nor->controller_ops->write(nor, to, len, buf);
>> >>>  }
>> >>>
>> >>> +/**
>> >>> + * spi_nor_read_reg() - read register to flash memory
>> >>> + * @nor:        pointer to 'struct spi_nor'.
>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>> >>> + * @proto:  SPI protocol to use for the register operation.
>> >>> + *
>> >>> + * Return: zero on success, -errno otherwise
>> >>> + */
>> >>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> >>> +                 enum spi_nor_protocol proto)
>> >>> +{
>> >>> +    if (!nor->spimem)
>> >>> +            return -EOPNOTSUPP;
>> >>> +
>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
>> >>> +    return spi_nor_spimem_exec_op(nor, op);
>> >>> +}
>> >>> +
>> >>> +/**
>> >>> + * spi_nor_write_reg() - write register to flash memory
>> >>> + * @nor:        pointer to 'struct spi_nor'
>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>> >>> + * @proto:  SPI protocol to use for the register operation.
>> >>> + *
>> >>> + * Return: zero on success, -errno otherwise
>> >>> + */
>> >>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> >>> +                  enum spi_nor_protocol proto)
>> >>> +{
>> >>> +    int ret;
>> >>> +
>> >>> +    if (!nor->spimem)
>> >>> +            return -EOPNOTSUPP;
>> >>> +
>> >>> +    ret = spi_nor_write_enable(nor);
>> >>> +    if (ret)
>> >>> +            return ret;
>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
>> >>> +    return spi_nor_spimem_exec_op(nor, op);
>> >
>> > After seeing your next two patches. Shouldn't the
>> > spi_nor_wait_until_ready() call be here too?
>> >
>> 
>> I thought of this too, but seems that for a reason that I don't
>> remember, we don't call for spi_nor_wait_until_ready after we
>> write the octal DTR bit. Pratyush, do you remember why?
> 
> We are not sure the protocol changed correctly so we can't rely on
> spi_nor_wait_until_ready(). We read the ID instead to be sure.

So besides the fact that the write_reg only works with the 'correct'
op parameter, it is also tailored to the special use case. For real
write_reg(), the user would actually has to poll the status bit
afterwards? :(

-michael

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-19 12:46             ` Michael Walle
@ 2022-04-19 12:56               ` Tudor.Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-19 12:56 UTC (permalink / raw)
  To: michael, p.yadav
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	Nicolas.Ferre, Takahiro.Kuwano

On 4/19/22 15:46, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2022-04-19 14:32, schrieb Pratyush Yadav:
>> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>>> On 4/19/22 14:46, Michael Walle wrote:
>>> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>> >
>>> > Am 2022-04-19 13:19, schrieb Michael Walle:
>>> >> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>> >>> There are manufacturers that use registers indexed by address. Some of
>>> >>> them support "read/write any register" opcodes. Provide core methods
>>> >>> that
>>> >>> can be used by all manufacturers. SPI NOR controller ops are
>>> >>> intentionally
>>> >>> not supported as we intend to move all the SPI NOR controller drivers
>>> >>> under the SPI subsystem.
>>> >>>
>>> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>> >>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>> >>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>> >>
>>> >> I still don't like it because the function doesn't do
>>> >> anything what the function name might suggest. The read
>>> >> just executes an op, the write executes an op with a
>>> >> write enable before. All the behavior is determined by the
>>> >> 'op' argument.
>>> >>
>>> >> Anyway,
>>> >> Reviewed-by: Michael Walle <michael@walle.cc>
>>> >>
>>> >>> ---
>>> >>> v3: no changes
>>> >>>
>>> >>>  drivers/mtd/spi-nor/core.c | 41
>>> >>> ++++++++++++++++++++++++++++++++++++++
>>> >>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>> >>>  2 files changed, 45 insertions(+)
>>> >>>
>>> >>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>> >>> index 6165dc7bfd17..42794328d3b6 100644
>>> >>> --- a/drivers/mtd/spi-nor/core.c
>>> >>> +++ b/drivers/mtd/spi-nor/core.c
>>> >>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>> >>> loff_t to, size_t len,
>>> >>>      return nor->controller_ops->write(nor, to, len, buf);
>>> >>>  }
>>> >>>
>>> >>> +/**
>>> >>> + * spi_nor_read_reg() - read register to flash memory
>>> >>> + * @nor:        pointer to 'struct spi_nor'.
>>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>> >>> + * @proto:  SPI protocol to use for the register operation.
>>> >>> + *
>>> >>> + * Return: zero on success, -errno otherwise
>>> >>> + */
>>> >>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>> >>> +                 enum spi_nor_protocol proto)
>>> >>> +{
>>> >>> +    if (!nor->spimem)
>>> >>> +            return -EOPNOTSUPP;
>>> >>> +
>>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>> >>> +    return spi_nor_spimem_exec_op(nor, op);
>>> >>> +}
>>> >>> +
>>> >>> +/**
>>> >>> + * spi_nor_write_reg() - write register to flash memory
>>> >>> + * @nor:        pointer to 'struct spi_nor'
>>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>> >>> + * @proto:  SPI protocol to use for the register operation.
>>> >>> + *
>>> >>> + * Return: zero on success, -errno otherwise
>>> >>> + */
>>> >>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>> >>> +                  enum spi_nor_protocol proto)
>>> >>> +{
>>> >>> +    int ret;
>>> >>> +
>>> >>> +    if (!nor->spimem)
>>> >>> +            return -EOPNOTSUPP;
>>> >>> +
>>> >>> +    ret = spi_nor_write_enable(nor);
>>> >>> +    if (ret)
>>> >>> +            return ret;
>>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>> >>> +    return spi_nor_spimem_exec_op(nor, op);
>>> >
>>> > After seeing your next two patches. Shouldn't the
>>> > spi_nor_wait_until_ready() call be here too?
>>> >
>>>
>>> I thought of this too, but seems that for a reason that I don't
>>> remember, we don't call for spi_nor_wait_until_ready after we
>>> write the octal DTR bit. Pratyush, do you remember why?
>>
>> We are not sure the protocol changed correctly so we can't rely on
>> spi_nor_wait_until_ready(). We read the ID instead to be sure.
> 
> So besides the fact that the write_reg only works with the 'correct'
> op parameter, it is also tailored to the special use case. For real
> write_reg(), the user would actually has to poll the status bit
> afterwards? :(
> 
Don't be sad :D. Are the octal DTR methods an exception?
If yes, let's add the call to spi_nor_wait_until_ready() in the
read/write_any_reg() methods, and let the octal methods handle
the specific write themselves, without calling for ready()

Cheers,
ta

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-19 12:56               ` Tudor.Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-19 12:56 UTC (permalink / raw)
  To: michael, p.yadav
  Cc: miquel.raynal, richard, vigneshr, linux-mtd, linux-kernel,
	Nicolas.Ferre, Takahiro.Kuwano

On 4/19/22 15:46, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2022-04-19 14:32, schrieb Pratyush Yadav:
>> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>>> On 4/19/22 14:46, Michael Walle wrote:
>>> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>> >
>>> > Am 2022-04-19 13:19, schrieb Michael Walle:
>>> >> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>> >>> There are manufacturers that use registers indexed by address. Some of
>>> >>> them support "read/write any register" opcodes. Provide core methods
>>> >>> that
>>> >>> can be used by all manufacturers. SPI NOR controller ops are
>>> >>> intentionally
>>> >>> not supported as we intend to move all the SPI NOR controller drivers
>>> >>> under the SPI subsystem.
>>> >>>
>>> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>> >>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>> >>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>> >>
>>> >> I still don't like it because the function doesn't do
>>> >> anything what the function name might suggest. The read
>>> >> just executes an op, the write executes an op with a
>>> >> write enable before. All the behavior is determined by the
>>> >> 'op' argument.
>>> >>
>>> >> Anyway,
>>> >> Reviewed-by: Michael Walle <michael@walle.cc>
>>> >>
>>> >>> ---
>>> >>> v3: no changes
>>> >>>
>>> >>>  drivers/mtd/spi-nor/core.c | 41
>>> >>> ++++++++++++++++++++++++++++++++++++++
>>> >>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>> >>>  2 files changed, 45 insertions(+)
>>> >>>
>>> >>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>> >>> index 6165dc7bfd17..42794328d3b6 100644
>>> >>> --- a/drivers/mtd/spi-nor/core.c
>>> >>> +++ b/drivers/mtd/spi-nor/core.c
>>> >>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>> >>> loff_t to, size_t len,
>>> >>>      return nor->controller_ops->write(nor, to, len, buf);
>>> >>>  }
>>> >>>
>>> >>> +/**
>>> >>> + * spi_nor_read_reg() - read register to flash memory
>>> >>> + * @nor:        pointer to 'struct spi_nor'.
>>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>> >>> + * @proto:  SPI protocol to use for the register operation.
>>> >>> + *
>>> >>> + * Return: zero on success, -errno otherwise
>>> >>> + */
>>> >>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>> >>> +                 enum spi_nor_protocol proto)
>>> >>> +{
>>> >>> +    if (!nor->spimem)
>>> >>> +            return -EOPNOTSUPP;
>>> >>> +
>>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>> >>> +    return spi_nor_spimem_exec_op(nor, op);
>>> >>> +}
>>> >>> +
>>> >>> +/**
>>> >>> + * spi_nor_write_reg() - write register to flash memory
>>> >>> + * @nor:        pointer to 'struct spi_nor'
>>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>> >>> + * @proto:  SPI protocol to use for the register operation.
>>> >>> + *
>>> >>> + * Return: zero on success, -errno otherwise
>>> >>> + */
>>> >>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>> >>> +                  enum spi_nor_protocol proto)
>>> >>> +{
>>> >>> +    int ret;
>>> >>> +
>>> >>> +    if (!nor->spimem)
>>> >>> +            return -EOPNOTSUPP;
>>> >>> +
>>> >>> +    ret = spi_nor_write_enable(nor);
>>> >>> +    if (ret)
>>> >>> +            return ret;
>>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>> >>> +    return spi_nor_spimem_exec_op(nor, op);
>>> >
>>> > After seeing your next two patches. Shouldn't the
>>> > spi_nor_wait_until_ready() call be here too?
>>> >
>>>
>>> I thought of this too, but seems that for a reason that I don't
>>> remember, we don't call for spi_nor_wait_until_ready after we
>>> write the octal DTR bit. Pratyush, do you remember why?
>>
>> We are not sure the protocol changed correctly so we can't rely on
>> spi_nor_wait_until_ready(). We read the ID instead to be sure.
> 
> So besides the fact that the write_reg only works with the 'correct'
> op parameter, it is also tailored to the special use case. For real
> write_reg(), the user would actually has to poll the status bit
> afterwards? :(
> 
Don't be sad :D. Are the octal DTR methods an exception?
If yes, let's add the call to spi_nor_wait_until_ready() in the
read/write_any_reg() methods, and let the octal methods handle
the specific write themselves, without calling for ready()

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-19 11:19     ` Michael Walle
@ 2022-04-19 12:59       ` Tudor.Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-19 12:59 UTC (permalink / raw)
  To: michael
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 4/19/22 14:19, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>> There are manufacturers that use registers indexed by address. Some of
>> them support "read/write any register" opcodes. Provide core methods
>> that
>> can be used by all manufacturers. SPI NOR controller ops are
>> intentionally
>> not supported as we intend to move all the SPI NOR controller drivers
>> under the SPI subsystem.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
> 
> I still don't like it because the function doesn't do
> anything what the function name might suggest. The read

is spi_nor_read_any_reg a better name than spi_nor_read_reg?


> just executes an op, the write executes an op with a
> write enable before. All the behavior is determined by the
> 'op' argument.

it still avoids code duplication, doesn't it?

Thanks,
ta
> 
> Anyway,
> Reviewed-by: Michael Walle <michael@walle.cc>
> 
>> ---
>> v3: no changes
>>
>>  drivers/mtd/spi-nor/core.c | 41 ++++++++++++++++++++++++++++++++++++++
>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>  2 files changed, 45 insertions(+)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 6165dc7bfd17..42794328d3b6 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>> loff_t to, size_t len,
>>       return nor->controller_ops->write(nor, to, len, buf);
>>  }
>>
>> +/**
>> + * spi_nor_read_reg() - read register to flash memory
>> + * @nor:        pointer to 'struct spi_nor'.
>> + * @op:              SPI memory operation. op->data.buf must be DMA-able.
>> + * @proto:   SPI protocol to use for the register operation.
>> + *
>> + * Return: zero on success, -errno otherwise
>> + */
>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +                  enum spi_nor_protocol proto)
>> +{
>> +     if (!nor->spimem)
>> +             return -EOPNOTSUPP;
>> +
>> +     spi_nor_spimem_setup_op(nor, op, proto);
>> +     return spi_nor_spimem_exec_op(nor, op);
>> +}
>> +
>> +/**
>> + * spi_nor_write_reg() - write register to flash memory
>> + * @nor:        pointer to 'struct spi_nor'
>> + * @op:              SPI memory operation. op->data.buf must be DMA-able.
>> + * @proto:   SPI protocol to use for the register operation.
>> + *
>> + * Return: zero on success, -errno otherwise
>> + */
>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +                   enum spi_nor_protocol proto)
>> +{
>> +     int ret;
>> +
>> +     if (!nor->spimem)
>> +             return -EOPNOTSUPP;
>> +
>> +     ret = spi_nor_write_enable(nor);
>> +     if (ret)
>> +             return ret;
>> +     spi_nor_spimem_setup_op(nor, op, proto);
>> +     return spi_nor_spimem_exec_op(nor, op);
>> +}
>> +
>>  /**
>>   * spi_nor_write_enable() - Set write enable latch with Write Enable
>> command.
>>   * @nor:     pointer to 'struct spi_nor'.
>> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> index f952061d5c24..7c704475946d 100644
>> --- a/drivers/mtd/spi-nor/core.h
>> +++ b/drivers/mtd/spi-nor/core.h
>> @@ -554,6 +554,10 @@ 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_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +                  enum spi_nor_protocol proto);
>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +                   enum spi_nor_protocol proto);
>>  int spi_nor_erase_sector(struct spi_nor *nor, u32 addr);
>>
>>  int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t
>> len, u8 *buf);
> 
> -- 
> -michael


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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-19 12:59       ` Tudor.Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-19 12:59 UTC (permalink / raw)
  To: michael
  Cc: p.yadav, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 4/19/22 14:19, Michael Walle wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>> There are manufacturers that use registers indexed by address. Some of
>> them support "read/write any register" opcodes. Provide core methods
>> that
>> can be used by all manufacturers. SPI NOR controller ops are
>> intentionally
>> not supported as we intend to move all the SPI NOR controller drivers
>> under the SPI subsystem.
>>
>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
> 
> I still don't like it because the function doesn't do
> anything what the function name might suggest. The read

is spi_nor_read_any_reg a better name than spi_nor_read_reg?


> just executes an op, the write executes an op with a
> write enable before. All the behavior is determined by the
> 'op' argument.

it still avoids code duplication, doesn't it?

Thanks,
ta
> 
> Anyway,
> Reviewed-by: Michael Walle <michael@walle.cc>
> 
>> ---
>> v3: no changes
>>
>>  drivers/mtd/spi-nor/core.c | 41 ++++++++++++++++++++++++++++++++++++++
>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>  2 files changed, 45 insertions(+)
>>
>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>> index 6165dc7bfd17..42794328d3b6 100644
>> --- a/drivers/mtd/spi-nor/core.c
>> +++ b/drivers/mtd/spi-nor/core.c
>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>> loff_t to, size_t len,
>>       return nor->controller_ops->write(nor, to, len, buf);
>>  }
>>
>> +/**
>> + * spi_nor_read_reg() - read register to flash memory
>> + * @nor:        pointer to 'struct spi_nor'.
>> + * @op:              SPI memory operation. op->data.buf must be DMA-able.
>> + * @proto:   SPI protocol to use for the register operation.
>> + *
>> + * Return: zero on success, -errno otherwise
>> + */
>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +                  enum spi_nor_protocol proto)
>> +{
>> +     if (!nor->spimem)
>> +             return -EOPNOTSUPP;
>> +
>> +     spi_nor_spimem_setup_op(nor, op, proto);
>> +     return spi_nor_spimem_exec_op(nor, op);
>> +}
>> +
>> +/**
>> + * spi_nor_write_reg() - write register to flash memory
>> + * @nor:        pointer to 'struct spi_nor'
>> + * @op:              SPI memory operation. op->data.buf must be DMA-able.
>> + * @proto:   SPI protocol to use for the register operation.
>> + *
>> + * Return: zero on success, -errno otherwise
>> + */
>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +                   enum spi_nor_protocol proto)
>> +{
>> +     int ret;
>> +
>> +     if (!nor->spimem)
>> +             return -EOPNOTSUPP;
>> +
>> +     ret = spi_nor_write_enable(nor);
>> +     if (ret)
>> +             return ret;
>> +     spi_nor_spimem_setup_op(nor, op, proto);
>> +     return spi_nor_spimem_exec_op(nor, op);
>> +}
>> +
>>  /**
>>   * spi_nor_write_enable() - Set write enable latch with Write Enable
>> command.
>>   * @nor:     pointer to 'struct spi_nor'.
>> diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
>> index f952061d5c24..7c704475946d 100644
>> --- a/drivers/mtd/spi-nor/core.h
>> +++ b/drivers/mtd/spi-nor/core.h
>> @@ -554,6 +554,10 @@ 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_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +                  enum spi_nor_protocol proto);
>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>> +                   enum spi_nor_protocol proto);
>>  int spi_nor_erase_sector(struct spi_nor *nor, u32 addr);
>>
>>  int spi_nor_otp_read_secr(struct spi_nor *nor, loff_t addr, size_t
>> len, u8 *buf);
> 
> -- 
> -michael

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-19 12:32           ` Pratyush Yadav
@ 2022-04-19 13:02             ` Tudor.Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-19 13:02 UTC (permalink / raw)
  To: p.yadav
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 4/19/22 15:32, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>> On 4/19/22 14:46, Michael Walle wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Am 2022-04-19 13:19, schrieb Michael Walle:
>>>> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>>>> There are manufacturers that use registers indexed by address. Some of
>>>>> them support "read/write any register" opcodes. Provide core methods
>>>>> that
>>>>> can be used by all manufacturers. SPI NOR controller ops are
>>>>> intentionally
>>>>> not supported as we intend to move all the SPI NOR controller drivers
>>>>> under the SPI subsystem.
>>>>>
>>>>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>>>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>>>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>>>
>>>> I still don't like it because the function doesn't do
>>>> anything what the function name might suggest. The read
>>>> just executes an op, the write executes an op with a
>>>> write enable before. All the behavior is determined by the
>>>> 'op' argument.
>>>>
>>>> Anyway,
>>>> Reviewed-by: Michael Walle <michael@walle.cc>
>>>>
>>>>> ---
>>>>> v3: no changes
>>>>>
>>>>>  drivers/mtd/spi-nor/core.c | 41
>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>>>>  2 files changed, 45 insertions(+)
>>>>>
>>>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>>>> index 6165dc7bfd17..42794328d3b6 100644
>>>>> --- a/drivers/mtd/spi-nor/core.c
>>>>> +++ b/drivers/mtd/spi-nor/core.c
>>>>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>>>> loff_t to, size_t len,
>>>>>      return nor->controller_ops->write(nor, to, len, buf);
>>>>>  }
>>>>>
>>>>> +/**
>>>>> + * spi_nor_read_reg() - read register to flash memory
>>>>> + * @nor:        pointer to 'struct spi_nor'.
>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>> + *
>>>>> + * Return: zero on success, -errno otherwise
>>>>> + */
>>>>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>> +                 enum spi_nor_protocol proto)
>>>>> +{
>>>>> +    if (!nor->spimem)
>>>>> +            return -EOPNOTSUPP;
>>>>> +
>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * spi_nor_write_reg() - write register to flash memory
>>>>> + * @nor:        pointer to 'struct spi_nor'
>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>> + *
>>>>> + * Return: zero on success, -errno otherwise
>>>>> + */
>>>>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>> +                  enum spi_nor_protocol proto)
>>>>> +{
>>>>> +    int ret;
>>>>> +
>>>>> +    if (!nor->spimem)
>>>>> +            return -EOPNOTSUPP;
>>>>> +
>>>>> +    ret = spi_nor_write_enable(nor);
>>>>> +    if (ret)
>>>>> +            return ret;
>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>
>>> After seeing your next two patches. Shouldn't the
>>> spi_nor_wait_until_ready() call be here too?
>>>
>>
>> I thought of this too, but seems that for a reason that I don't
>> remember, we don't call for spi_nor_wait_until_ready after we
>> write the octal DTR bit. Pratyush, do you remember why?
> 
> We are not sure the protocol changed correctly so we can't rely on
> spi_nor_wait_until_ready(). We read the ID instead to be sure.
> 

But it is still recommended to check for the WIP bit, isn't it?

cheers,
ta

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-19 13:02             ` Tudor.Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-19 13:02 UTC (permalink / raw)
  To: p.yadav
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 4/19/22 15:32, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>> On 4/19/22 14:46, Michael Walle wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Am 2022-04-19 13:19, schrieb Michael Walle:
>>>> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>>>> There are manufacturers that use registers indexed by address. Some of
>>>>> them support "read/write any register" opcodes. Provide core methods
>>>>> that
>>>>> can be used by all manufacturers. SPI NOR controller ops are
>>>>> intentionally
>>>>> not supported as we intend to move all the SPI NOR controller drivers
>>>>> under the SPI subsystem.
>>>>>
>>>>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>>>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>>>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>>>
>>>> I still don't like it because the function doesn't do
>>>> anything what the function name might suggest. The read
>>>> just executes an op, the write executes an op with a
>>>> write enable before. All the behavior is determined by the
>>>> 'op' argument.
>>>>
>>>> Anyway,
>>>> Reviewed-by: Michael Walle <michael@walle.cc>
>>>>
>>>>> ---
>>>>> v3: no changes
>>>>>
>>>>>  drivers/mtd/spi-nor/core.c | 41
>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>  drivers/mtd/spi-nor/core.h |  4 ++++
>>>>>  2 files changed, 45 insertions(+)
>>>>>
>>>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>>>> index 6165dc7bfd17..42794328d3b6 100644
>>>>> --- a/drivers/mtd/spi-nor/core.c
>>>>> +++ b/drivers/mtd/spi-nor/core.c
>>>>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>>>> loff_t to, size_t len,
>>>>>      return nor->controller_ops->write(nor, to, len, buf);
>>>>>  }
>>>>>
>>>>> +/**
>>>>> + * spi_nor_read_reg() - read register to flash memory
>>>>> + * @nor:        pointer to 'struct spi_nor'.
>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>> + *
>>>>> + * Return: zero on success, -errno otherwise
>>>>> + */
>>>>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>> +                 enum spi_nor_protocol proto)
>>>>> +{
>>>>> +    if (!nor->spimem)
>>>>> +            return -EOPNOTSUPP;
>>>>> +
>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>> +}
>>>>> +
>>>>> +/**
>>>>> + * spi_nor_write_reg() - write register to flash memory
>>>>> + * @nor:        pointer to 'struct spi_nor'
>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>> + *
>>>>> + * Return: zero on success, -errno otherwise
>>>>> + */
>>>>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>> +                  enum spi_nor_protocol proto)
>>>>> +{
>>>>> +    int ret;
>>>>> +
>>>>> +    if (!nor->spimem)
>>>>> +            return -EOPNOTSUPP;
>>>>> +
>>>>> +    ret = spi_nor_write_enable(nor);
>>>>> +    if (ret)
>>>>> +            return ret;
>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>
>>> After seeing your next two patches. Shouldn't the
>>> spi_nor_wait_until_ready() call be here too?
>>>
>>
>> I thought of this too, but seems that for a reason that I don't
>> remember, we don't call for spi_nor_wait_until_ready after we
>> write the octal DTR bit. Pratyush, do you remember why?
> 
> We are not sure the protocol changed correctly so we can't rely on
> spi_nor_wait_until_ready(). We read the ID instead to be sure.
> 

But it is still recommended to check for the WIP bit, isn't it?

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-19 12:56               ` Tudor.Ambarus
@ 2022-04-20  4:34                 ` Pratyush Yadav
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Yadav @ 2022-04-20  4:34 UTC (permalink / raw)
  To: Tudor.Ambarus
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 19/04/22 12:56PM, Tudor.Ambarus@microchip.com wrote:
> On 4/19/22 15:46, Michael Walle wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > Am 2022-04-19 14:32, schrieb Pratyush Yadav:
> >> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
> >>> On 4/19/22 14:46, Michael Walle wrote:
> >>> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >>> >
> >>> > Am 2022-04-19 13:19, schrieb Michael Walle:
> >>> >> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> >>> >>> There are manufacturers that use registers indexed by address. Some of
> >>> >>> them support "read/write any register" opcodes. Provide core methods
> >>> >>> that
> >>> >>> can be used by all manufacturers. SPI NOR controller ops are
> >>> >>> intentionally
> >>> >>> not supported as we intend to move all the SPI NOR controller drivers
> >>> >>> under the SPI subsystem.
> >>> >>>
> >>> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> >>> >>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> >>> >>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
> >>> >>
> >>> >> I still don't like it because the function doesn't do
> >>> >> anything what the function name might suggest. The read
> >>> >> just executes an op, the write executes an op with a
> >>> >> write enable before. All the behavior is determined by the
> >>> >> 'op' argument.
> >>> >>
> >>> >> Anyway,
> >>> >> Reviewed-by: Michael Walle <michael@walle.cc>
> >>> >>
> >>> >>> ---
> >>> >>> v3: no changes
> >>> >>>
> >>> >>>  drivers/mtd/spi-nor/core.c | 41
> >>> >>> ++++++++++++++++++++++++++++++++++++++
> >>> >>>  drivers/mtd/spi-nor/core.h |  4 ++++
> >>> >>>  2 files changed, 45 insertions(+)
> >>> >>>
> >>> >>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> >>> >>> index 6165dc7bfd17..42794328d3b6 100644
> >>> >>> --- a/drivers/mtd/spi-nor/core.c
> >>> >>> +++ b/drivers/mtd/spi-nor/core.c
> >>> >>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
> >>> >>> loff_t to, size_t len,
> >>> >>>      return nor->controller_ops->write(nor, to, len, buf);
> >>> >>>  }
> >>> >>>
> >>> >>> +/**
> >>> >>> + * spi_nor_read_reg() - read register to flash memory
> >>> >>> + * @nor:        pointer to 'struct spi_nor'.
> >>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
> >>> >>> + * @proto:  SPI protocol to use for the register operation.
> >>> >>> + *
> >>> >>> + * Return: zero on success, -errno otherwise
> >>> >>> + */
> >>> >>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
> >>> >>> +                 enum spi_nor_protocol proto)
> >>> >>> +{
> >>> >>> +    if (!nor->spimem)
> >>> >>> +            return -EOPNOTSUPP;
> >>> >>> +
> >>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
> >>> >>> +    return spi_nor_spimem_exec_op(nor, op);
> >>> >>> +}
> >>> >>> +
> >>> >>> +/**
> >>> >>> + * spi_nor_write_reg() - write register to flash memory
> >>> >>> + * @nor:        pointer to 'struct spi_nor'
> >>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
> >>> >>> + * @proto:  SPI protocol to use for the register operation.
> >>> >>> + *
> >>> >>> + * Return: zero on success, -errno otherwise
> >>> >>> + */
> >>> >>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
> >>> >>> +                  enum spi_nor_protocol proto)
> >>> >>> +{
> >>> >>> +    int ret;
> >>> >>> +
> >>> >>> +    if (!nor->spimem)
> >>> >>> +            return -EOPNOTSUPP;
> >>> >>> +
> >>> >>> +    ret = spi_nor_write_enable(nor);
> >>> >>> +    if (ret)
> >>> >>> +            return ret;
> >>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
> >>> >>> +    return spi_nor_spimem_exec_op(nor, op);
> >>> >
> >>> > After seeing your next two patches. Shouldn't the
> >>> > spi_nor_wait_until_ready() call be here too?
> >>> >
> >>>
> >>> I thought of this too, but seems that for a reason that I don't
> >>> remember, we don't call for spi_nor_wait_until_ready after we
> >>> write the octal DTR bit. Pratyush, do you remember why?
> >>
> >> We are not sure the protocol changed correctly so we can't rely on
> >> spi_nor_wait_until_ready(). We read the ID instead to be sure.
> > 
> > So besides the fact that the write_reg only works with the 'correct'
> > op parameter, it is also tailored to the special use case. For real
> > write_reg(), the user would actually has to poll the status bit
> > afterwards? :(
> > 
> Don't be sad :D. Are the octal DTR methods an exception?
> If yes, let's add the call to spi_nor_wait_until_ready() in the
> read/write_any_reg() methods, and let the octal methods handle
> the specific write themselves, without calling for ready()

It has been a while, but IIRC I asked Cypress about this, because I was 
worried about reading ID while the switch to 8D mode was still in 
progress. They said that volatile register writes are instant and do not 
need any status polling. So the switch to 8D-8D-8D mode would be instant 
and there is no need to wait for anything.

The Cypress S28 flash datasheet does not say this explicitly. It does 
say that writing to non-volatile registers takes time and you need to 
wait for ready for those, but makes no mention of volatile registers. We 
don't ever want to write non-volatile registers so we can ignore that 
problem.

I see the Micron MT35 datasheet say this explicitly, that changes to 
volatile registers are instant.

So I would say that based on my limited sample size, volatile register 
writes for Cypress and Micron flashes do _not_ need 
spi_nor_wait_until_ready().

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-20  4:34                 ` Pratyush Yadav
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Yadav @ 2022-04-20  4:34 UTC (permalink / raw)
  To: Tudor.Ambarus
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 19/04/22 12:56PM, Tudor.Ambarus@microchip.com wrote:
> On 4/19/22 15:46, Michael Walle wrote:
> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> > 
> > Am 2022-04-19 14:32, schrieb Pratyush Yadav:
> >> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
> >>> On 4/19/22 14:46, Michael Walle wrote:
> >>> > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> >>> >
> >>> > Am 2022-04-19 13:19, schrieb Michael Walle:
> >>> >> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> >>> >>> There are manufacturers that use registers indexed by address. Some of
> >>> >>> them support "read/write any register" opcodes. Provide core methods
> >>> >>> that
> >>> >>> can be used by all manufacturers. SPI NOR controller ops are
> >>> >>> intentionally
> >>> >>> not supported as we intend to move all the SPI NOR controller drivers
> >>> >>> under the SPI subsystem.
> >>> >>>
> >>> >>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> >>> >>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
> >>> >>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
> >>> >>
> >>> >> I still don't like it because the function doesn't do
> >>> >> anything what the function name might suggest. The read
> >>> >> just executes an op, the write executes an op with a
> >>> >> write enable before. All the behavior is determined by the
> >>> >> 'op' argument.
> >>> >>
> >>> >> Anyway,
> >>> >> Reviewed-by: Michael Walle <michael@walle.cc>
> >>> >>
> >>> >>> ---
> >>> >>> v3: no changes
> >>> >>>
> >>> >>>  drivers/mtd/spi-nor/core.c | 41
> >>> >>> ++++++++++++++++++++++++++++++++++++++
> >>> >>>  drivers/mtd/spi-nor/core.h |  4 ++++
> >>> >>>  2 files changed, 45 insertions(+)
> >>> >>>
> >>> >>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
> >>> >>> index 6165dc7bfd17..42794328d3b6 100644
> >>> >>> --- a/drivers/mtd/spi-nor/core.c
> >>> >>> +++ b/drivers/mtd/spi-nor/core.c
> >>> >>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
> >>> >>> loff_t to, size_t len,
> >>> >>>      return nor->controller_ops->write(nor, to, len, buf);
> >>> >>>  }
> >>> >>>
> >>> >>> +/**
> >>> >>> + * spi_nor_read_reg() - read register to flash memory
> >>> >>> + * @nor:        pointer to 'struct spi_nor'.
> >>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
> >>> >>> + * @proto:  SPI protocol to use for the register operation.
> >>> >>> + *
> >>> >>> + * Return: zero on success, -errno otherwise
> >>> >>> + */
> >>> >>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
> >>> >>> +                 enum spi_nor_protocol proto)
> >>> >>> +{
> >>> >>> +    if (!nor->spimem)
> >>> >>> +            return -EOPNOTSUPP;
> >>> >>> +
> >>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
> >>> >>> +    return spi_nor_spimem_exec_op(nor, op);
> >>> >>> +}
> >>> >>> +
> >>> >>> +/**
> >>> >>> + * spi_nor_write_reg() - write register to flash memory
> >>> >>> + * @nor:        pointer to 'struct spi_nor'
> >>> >>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
> >>> >>> + * @proto:  SPI protocol to use for the register operation.
> >>> >>> + *
> >>> >>> + * Return: zero on success, -errno otherwise
> >>> >>> + */
> >>> >>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
> >>> >>> +                  enum spi_nor_protocol proto)
> >>> >>> +{
> >>> >>> +    int ret;
> >>> >>> +
> >>> >>> +    if (!nor->spimem)
> >>> >>> +            return -EOPNOTSUPP;
> >>> >>> +
> >>> >>> +    ret = spi_nor_write_enable(nor);
> >>> >>> +    if (ret)
> >>> >>> +            return ret;
> >>> >>> +    spi_nor_spimem_setup_op(nor, op, proto);
> >>> >>> +    return spi_nor_spimem_exec_op(nor, op);
> >>> >
> >>> > After seeing your next two patches. Shouldn't the
> >>> > spi_nor_wait_until_ready() call be here too?
> >>> >
> >>>
> >>> I thought of this too, but seems that for a reason that I don't
> >>> remember, we don't call for spi_nor_wait_until_ready after we
> >>> write the octal DTR bit. Pratyush, do you remember why?
> >>
> >> We are not sure the protocol changed correctly so we can't rely on
> >> spi_nor_wait_until_ready(). We read the ID instead to be sure.
> > 
> > So besides the fact that the write_reg only works with the 'correct'
> > op parameter, it is also tailored to the special use case. For real
> > write_reg(), the user would actually has to poll the status bit
> > afterwards? :(
> > 
> Don't be sad :D. Are the octal DTR methods an exception?
> If yes, let's add the call to spi_nor_wait_until_ready() in the
> read/write_any_reg() methods, and let the octal methods handle
> the specific write themselves, without calling for ready()

It has been a while, but IIRC I asked Cypress about this, because I was 
worried about reading ID while the switch to 8D mode was still in 
progress. They said that volatile register writes are instant and do not 
need any status polling. So the switch to 8D-8D-8D mode would be instant 
and there is no need to wait for anything.

The Cypress S28 flash datasheet does not say this explicitly. It does 
say that writing to non-volatile registers takes time and you need to 
wait for ready for those, but makes no mention of volatile registers. We 
don't ever want to write non-volatile registers so we can ignore that 
problem.

I see the Micron MT35 datasheet say this explicitly, that changes to 
volatile registers are instant.

So I would say that based on my limited sample size, volatile register 
writes for Cypress and Micron flashes do _not_ need 
spi_nor_wait_until_ready().

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-20  4:34                 ` Pratyush Yadav
@ 2022-04-20  5:20                   ` Takahiro Kuwano
  -1 siblings, 0 replies; 56+ messages in thread
From: Takahiro Kuwano @ 2022-04-20  5:20 UTC (permalink / raw)
  To: Pratyush Yadav, Tudor.Ambarus
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano



On 4/20/2022 1:34 PM, Pratyush Yadav wrote:
> On 19/04/22 12:56PM, Tudor.Ambarus@microchip.com wrote:
>> On 4/19/22 15:46, Michael Walle wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Am 2022-04-19 14:32, schrieb Pratyush Yadav:
>>>> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>>>>> On 4/19/22 14:46, Michael Walle wrote:
>>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>>>
>>>>>> Am 2022-04-19 13:19, schrieb Michael Walle:
>>>>>>> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>>>>>>> There are manufacturers that use registers indexed by address. Some of
>>>>>>>> them support "read/write any register" opcodes. Provide core methods
>>>>>>>> that
>>>>>>>> can be used by all manufacturers. SPI NOR controller ops are
>>>>>>>> intentionally
>>>>>>>> not supported as we intend to move all the SPI NOR controller drivers
>>>>>>>> under the SPI subsystem.
>>>>>>>>
>>>>>>>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>>>>>>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>>>>>>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>>>>>>
>>>>>>> I still don't like it because the function doesn't do
>>>>>>> anything what the function name might suggest. The read
>>>>>>> just executes an op, the write executes an op with a
>>>>>>> write enable before. All the behavior is determined by the
>>>>>>> 'op' argument.
>>>>>>>
>>>>>>> Anyway,
>>>>>>> Reviewed-by: Michael Walle <michael@walle.cc>
>>>>>>>
>>>>>>>> ---
>>>>>>>> v3: no changes
>>>>>>>>
>>>>>>>>   drivers/mtd/spi-nor/core.c | 41
>>>>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>>>>   drivers/mtd/spi-nor/core.h |  4 ++++
>>>>>>>>   2 files changed, 45 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>>>>>>> index 6165dc7bfd17..42794328d3b6 100644
>>>>>>>> --- a/drivers/mtd/spi-nor/core.c
>>>>>>>> +++ b/drivers/mtd/spi-nor/core.c
>>>>>>>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>>>>>>> loff_t to, size_t len,
>>>>>>>>       return nor->controller_ops->write(nor, to, len, buf);
>>>>>>>>   }
>>>>>>>>
>>>>>>>> +/**
>>>>>>>> + * spi_nor_read_reg() - read register to flash memory
>>>>>>>> + * @nor:        pointer to 'struct spi_nor'.
>>>>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>>>>> + *
>>>>>>>> + * Return: zero on success, -errno otherwise
>>>>>>>> + */
>>>>>>>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>>>>> +                 enum spi_nor_protocol proto)
>>>>>>>> +{
>>>>>>>> +    if (!nor->spimem)
>>>>>>>> +            return -EOPNOTSUPP;
>>>>>>>> +
>>>>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + * spi_nor_write_reg() - write register to flash memory
>>>>>>>> + * @nor:        pointer to 'struct spi_nor'
>>>>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>>>>> + *
>>>>>>>> + * Return: zero on success, -errno otherwise
>>>>>>>> + */
>>>>>>>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>>>>> +                  enum spi_nor_protocol proto)
>>>>>>>> +{
>>>>>>>> +    int ret;
>>>>>>>> +
>>>>>>>> +    if (!nor->spimem)
>>>>>>>> +            return -EOPNOTSUPP;
>>>>>>>> +
>>>>>>>> +    ret = spi_nor_write_enable(nor);
>>>>>>>> +    if (ret)
>>>>>>>> +            return ret;
>>>>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>>>
>>>>>> After seeing your next two patches. Shouldn't the
>>>>>> spi_nor_wait_until_ready() call be here too?
>>>>>>
>>>>>
>>>>> I thought of this too, but seems that for a reason that I don't
>>>>> remember, we don't call for spi_nor_wait_until_ready after we
>>>>> write the octal DTR bit. Pratyush, do you remember why?
>>>>
>>>> We are not sure the protocol changed correctly so we can't rely on
>>>> spi_nor_wait_until_ready(). We read the ID instead to be sure.
>>>
>>> So besides the fact that the write_reg only works with the 'correct'
>>> op parameter, it is also tailored to the special use case. For real
>>> write_reg(), the user would actually has to poll the status bit
>>> afterwards? :(
>>>
>> Don't be sad :D. Are the octal DTR methods an exception?
>> If yes, let's add the call to spi_nor_wait_until_ready() in the
>> read/write_any_reg() methods, and let the octal methods handle
>> the specific write themselves, without calling for ready()
> 
> It has been a while, but IIRC I asked Cypress about this, because I was 
> worried about reading ID while the switch to 8D mode was still in 
> progress. They said that volatile register writes are instant and do not 
> need any status polling. So the switch to 8D-8D-8D mode would be instant 
> and there is no need to wait for anything.
> 
Yes, it is correct.

> The Cypress S28 flash datasheet does not say this explicitly. It does 
It is what we (Infineon) need to solve...

> say that writing to non-volatile registers takes time and you need to 
> wait for ready for those, but makes no mention of volatile registers. We 
> don't ever want to write non-volatile registers so we can ignore that 
> problem.
> 
> I see the Micron MT35 datasheet say this explicitly, that changes to 
> volatile registers are instant.
> 
> So I would say that based on my limited sample size, volatile register 
> writes for Cypress and Micron flashes do _not_ need 
> spi_nor_wait_until_ready().
> 

Thanks,
Takahiro Kuwano

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-20  5:20                   ` Takahiro Kuwano
  0 siblings, 0 replies; 56+ messages in thread
From: Takahiro Kuwano @ 2022-04-20  5:20 UTC (permalink / raw)
  To: Pratyush Yadav, Tudor.Ambarus
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano



On 4/20/2022 1:34 PM, Pratyush Yadav wrote:
> On 19/04/22 12:56PM, Tudor.Ambarus@microchip.com wrote:
>> On 4/19/22 15:46, Michael Walle wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Am 2022-04-19 14:32, schrieb Pratyush Yadav:
>>>> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>>>>> On 4/19/22 14:46, Michael Walle wrote:
>>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>>>
>>>>>> Am 2022-04-19 13:19, schrieb Michael Walle:
>>>>>>> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>>>>>>> There are manufacturers that use registers indexed by address. Some of
>>>>>>>> them support "read/write any register" opcodes. Provide core methods
>>>>>>>> that
>>>>>>>> can be used by all manufacturers. SPI NOR controller ops are
>>>>>>>> intentionally
>>>>>>>> not supported as we intend to move all the SPI NOR controller drivers
>>>>>>>> under the SPI subsystem.
>>>>>>>>
>>>>>>>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>>>>>>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>>>>>>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>>>>>>
>>>>>>> I still don't like it because the function doesn't do
>>>>>>> anything what the function name might suggest. The read
>>>>>>> just executes an op, the write executes an op with a
>>>>>>> write enable before. All the behavior is determined by the
>>>>>>> 'op' argument.
>>>>>>>
>>>>>>> Anyway,
>>>>>>> Reviewed-by: Michael Walle <michael@walle.cc>
>>>>>>>
>>>>>>>> ---
>>>>>>>> v3: no changes
>>>>>>>>
>>>>>>>>   drivers/mtd/spi-nor/core.c | 41
>>>>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>>>>   drivers/mtd/spi-nor/core.h |  4 ++++
>>>>>>>>   2 files changed, 45 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>>>>>>> index 6165dc7bfd17..42794328d3b6 100644
>>>>>>>> --- a/drivers/mtd/spi-nor/core.c
>>>>>>>> +++ b/drivers/mtd/spi-nor/core.c
>>>>>>>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>>>>>>> loff_t to, size_t len,
>>>>>>>>       return nor->controller_ops->write(nor, to, len, buf);
>>>>>>>>   }
>>>>>>>>
>>>>>>>> +/**
>>>>>>>> + * spi_nor_read_reg() - read register to flash memory
>>>>>>>> + * @nor:        pointer to 'struct spi_nor'.
>>>>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>>>>> + *
>>>>>>>> + * Return: zero on success, -errno otherwise
>>>>>>>> + */
>>>>>>>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>>>>> +                 enum spi_nor_protocol proto)
>>>>>>>> +{
>>>>>>>> +    if (!nor->spimem)
>>>>>>>> +            return -EOPNOTSUPP;
>>>>>>>> +
>>>>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + * spi_nor_write_reg() - write register to flash memory
>>>>>>>> + * @nor:        pointer to 'struct spi_nor'
>>>>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>>>>> + *
>>>>>>>> + * Return: zero on success, -errno otherwise
>>>>>>>> + */
>>>>>>>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>>>>> +                  enum spi_nor_protocol proto)
>>>>>>>> +{
>>>>>>>> +    int ret;
>>>>>>>> +
>>>>>>>> +    if (!nor->spimem)
>>>>>>>> +            return -EOPNOTSUPP;
>>>>>>>> +
>>>>>>>> +    ret = spi_nor_write_enable(nor);
>>>>>>>> +    if (ret)
>>>>>>>> +            return ret;
>>>>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>>>
>>>>>> After seeing your next two patches. Shouldn't the
>>>>>> spi_nor_wait_until_ready() call be here too?
>>>>>>
>>>>>
>>>>> I thought of this too, but seems that for a reason that I don't
>>>>> remember, we don't call for spi_nor_wait_until_ready after we
>>>>> write the octal DTR bit. Pratyush, do you remember why?
>>>>
>>>> We are not sure the protocol changed correctly so we can't rely on
>>>> spi_nor_wait_until_ready(). We read the ID instead to be sure.
>>>
>>> So besides the fact that the write_reg only works with the 'correct'
>>> op parameter, it is also tailored to the special use case. For real
>>> write_reg(), the user would actually has to poll the status bit
>>> afterwards? :(
>>>
>> Don't be sad :D. Are the octal DTR methods an exception?
>> If yes, let's add the call to spi_nor_wait_until_ready() in the
>> read/write_any_reg() methods, and let the octal methods handle
>> the specific write themselves, without calling for ready()
> 
> It has been a while, but IIRC I asked Cypress about this, because I was 
> worried about reading ID while the switch to 8D mode was still in 
> progress. They said that volatile register writes are instant and do not 
> need any status polling. So the switch to 8D-8D-8D mode would be instant 
> and there is no need to wait for anything.
> 
Yes, it is correct.

> The Cypress S28 flash datasheet does not say this explicitly. It does 
It is what we (Infineon) need to solve...

> say that writing to non-volatile registers takes time and you need to 
> wait for ready for those, but makes no mention of volatile registers. We 
> don't ever want to write non-volatile registers so we can ignore that 
> problem.
> 
> I see the Micron MT35 datasheet say this explicitly, that changes to 
> volatile registers are instant.
> 
> So I would say that based on my limited sample size, volatile register 
> writes for Cypress and Micron flashes do _not_ need 
> spi_nor_wait_until_ready().
> 

Thanks,
Takahiro Kuwano

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

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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
  2022-04-20  4:34                 ` Pratyush Yadav
@ 2022-04-20  5:25                   ` Tudor.Ambarus
  -1 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-20  5:25 UTC (permalink / raw)
  To: p.yadav
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 4/20/22 07:34, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 19/04/22 12:56PM, Tudor.Ambarus@microchip.com wrote:
>> On 4/19/22 15:46, Michael Walle wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Am 2022-04-19 14:32, schrieb Pratyush Yadav:
>>>> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>>>>> On 4/19/22 14:46, Michael Walle wrote:
>>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>>>
>>>>>> Am 2022-04-19 13:19, schrieb Michael Walle:
>>>>>>> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>>>>>>> There are manufacturers that use registers indexed by address. Some of
>>>>>>>> them support "read/write any register" opcodes. Provide core methods
>>>>>>>> that
>>>>>>>> can be used by all manufacturers. SPI NOR controller ops are
>>>>>>>> intentionally
>>>>>>>> not supported as we intend to move all the SPI NOR controller drivers
>>>>>>>> under the SPI subsystem.
>>>>>>>>
>>>>>>>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>>>>>>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>>>>>>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>>>>>>
>>>>>>> I still don't like it because the function doesn't do
>>>>>>> anything what the function name might suggest. The read
>>>>>>> just executes an op, the write executes an op with a
>>>>>>> write enable before. All the behavior is determined by the
>>>>>>> 'op' argument.
>>>>>>>
>>>>>>> Anyway,
>>>>>>> Reviewed-by: Michael Walle <michael@walle.cc>
>>>>>>>
>>>>>>>> ---
>>>>>>>> v3: no changes
>>>>>>>>
>>>>>>>>   drivers/mtd/spi-nor/core.c | 41
>>>>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>>>>   drivers/mtd/spi-nor/core.h |  4 ++++
>>>>>>>>   2 files changed, 45 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>>>>>>> index 6165dc7bfd17..42794328d3b6 100644
>>>>>>>> --- a/drivers/mtd/spi-nor/core.c
>>>>>>>> +++ b/drivers/mtd/spi-nor/core.c
>>>>>>>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>>>>>>> loff_t to, size_t len,
>>>>>>>>       return nor->controller_ops->write(nor, to, len, buf);
>>>>>>>>   }
>>>>>>>>
>>>>>>>> +/**
>>>>>>>> + * spi_nor_read_reg() - read register to flash memory
>>>>>>>> + * @nor:        pointer to 'struct spi_nor'.
>>>>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>>>>> + *
>>>>>>>> + * Return: zero on success, -errno otherwise
>>>>>>>> + */
>>>>>>>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>>>>> +                 enum spi_nor_protocol proto)
>>>>>>>> +{
>>>>>>>> +    if (!nor->spimem)
>>>>>>>> +            return -EOPNOTSUPP;
>>>>>>>> +
>>>>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + * spi_nor_write_reg() - write register to flash memory
>>>>>>>> + * @nor:        pointer to 'struct spi_nor'
>>>>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>>>>> + *
>>>>>>>> + * Return: zero on success, -errno otherwise
>>>>>>>> + */
>>>>>>>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>>>>> +                  enum spi_nor_protocol proto)
>>>>>>>> +{
>>>>>>>> +    int ret;
>>>>>>>> +
>>>>>>>> +    if (!nor->spimem)
>>>>>>>> +            return -EOPNOTSUPP;
>>>>>>>> +
>>>>>>>> +    ret = spi_nor_write_enable(nor);
>>>>>>>> +    if (ret)
>>>>>>>> +            return ret;
>>>>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>>>
>>>>>> After seeing your next two patches. Shouldn't the
>>>>>> spi_nor_wait_until_ready() call be here too?
>>>>>>
>>>>>
>>>>> I thought of this too, but seems that for a reason that I don't
>>>>> remember, we don't call for spi_nor_wait_until_ready after we
>>>>> write the octal DTR bit. Pratyush, do you remember why?
>>>>
>>>> We are not sure the protocol changed correctly so we can't rely on
>>>> spi_nor_wait_until_ready(). We read the ID instead to be sure.
>>>
>>> So besides the fact that the write_reg only works with the 'correct'
>>> op parameter, it is also tailored to the special use case. For real
>>> write_reg(), the user would actually has to poll the status bit
>>> afterwards? :(
>>>
>> Don't be sad :D. Are the octal DTR methods an exception?
>> If yes, let's add the call to spi_nor_wait_until_ready() in the
>> read/write_any_reg() methods, and let the octal methods handle
>> the specific write themselves, without calling for ready()
> 
> It has been a while, but IIRC I asked Cypress about this, because I was
> worried about reading ID while the switch to 8D mode was still in
> progress. They said that volatile register writes are instant and do not
> need any status polling. So the switch to 8D-8D-8D mode would be instant
> and there is no need to wait for anything.
> 
> The Cypress S28 flash datasheet does not say this explicitly. It does
> say that writing to non-volatile registers takes time and you need to
> wait for ready for those, but makes no mention of volatile registers. We
> don't ever want to write non-volatile registers so we can ignore that
> problem.
> 
> I see the Micron MT35 datasheet say this explicitly, that changes to
> volatile registers are instant.
> 
> So I would say that based on my limited sample size, volatile register
> writes for Cypress and Micron flashes do _not_ need
> spi_nor_wait_until_ready().

Thanks, Pratyush! I'll add a comment and/or update the commit message,
this is useful info.

Cheers,
ta


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

* Re: [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register
@ 2022-04-20  5:25                   ` Tudor.Ambarus
  0 siblings, 0 replies; 56+ messages in thread
From: Tudor.Ambarus @ 2022-04-20  5:25 UTC (permalink / raw)
  To: p.yadav
  Cc: michael, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, Nicolas.Ferre, Takahiro.Kuwano

On 4/20/22 07:34, Pratyush Yadav wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> On 19/04/22 12:56PM, Tudor.Ambarus@microchip.com wrote:
>> On 4/19/22 15:46, Michael Walle wrote:
>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>
>>> Am 2022-04-19 14:32, schrieb Pratyush Yadav:
>>>> On 19/04/22 12:08PM, Tudor.Ambarus@microchip.com wrote:
>>>>> On 4/19/22 14:46, Michael Walle wrote:
>>>>>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
>>>>>>
>>>>>> Am 2022-04-19 13:19, schrieb Michael Walle:
>>>>>>> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
>>>>>>>> There are manufacturers that use registers indexed by address. Some of
>>>>>>>> them support "read/write any register" opcodes. Provide core methods
>>>>>>>> that
>>>>>>>> can be used by all manufacturers. SPI NOR controller ops are
>>>>>>>> intentionally
>>>>>>>> not supported as we intend to move all the SPI NOR controller drivers
>>>>>>>> under the SPI subsystem.
>>>>>>>>
>>>>>>>> Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
>>>>>>>> Tested-by: Takahiro Kuwano <Takahiro.Kuwano@infineon.com>
>>>>>>>> Reviewed-by: Pratyush Yadav <p.yadav@ti.com>
>>>>>>>
>>>>>>> I still don't like it because the function doesn't do
>>>>>>> anything what the function name might suggest. The read
>>>>>>> just executes an op, the write executes an op with a
>>>>>>> write enable before. All the behavior is determined by the
>>>>>>> 'op' argument.
>>>>>>>
>>>>>>> Anyway,
>>>>>>> Reviewed-by: Michael Walle <michael@walle.cc>
>>>>>>>
>>>>>>>> ---
>>>>>>>> v3: no changes
>>>>>>>>
>>>>>>>>   drivers/mtd/spi-nor/core.c | 41
>>>>>>>> ++++++++++++++++++++++++++++++++++++++
>>>>>>>>   drivers/mtd/spi-nor/core.h |  4 ++++
>>>>>>>>   2 files changed, 45 insertions(+)
>>>>>>>>
>>>>>>>> diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
>>>>>>>> index 6165dc7bfd17..42794328d3b6 100644
>>>>>>>> --- a/drivers/mtd/spi-nor/core.c
>>>>>>>> +++ b/drivers/mtd/spi-nor/core.c
>>>>>>>> @@ -307,6 +307,47 @@ ssize_t spi_nor_write_data(struct spi_nor *nor,
>>>>>>>> loff_t to, size_t len,
>>>>>>>>       return nor->controller_ops->write(nor, to, len, buf);
>>>>>>>>   }
>>>>>>>>
>>>>>>>> +/**
>>>>>>>> + * spi_nor_read_reg() - read register to flash memory
>>>>>>>> + * @nor:        pointer to 'struct spi_nor'.
>>>>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>>>>> + *
>>>>>>>> + * Return: zero on success, -errno otherwise
>>>>>>>> + */
>>>>>>>> +int spi_nor_read_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>>>>> +                 enum spi_nor_protocol proto)
>>>>>>>> +{
>>>>>>>> +    if (!nor->spimem)
>>>>>>>> +            return -EOPNOTSUPP;
>>>>>>>> +
>>>>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + * spi_nor_write_reg() - write register to flash memory
>>>>>>>> + * @nor:        pointer to 'struct spi_nor'
>>>>>>>> + * @op:             SPI memory operation. op->data.buf must be DMA-able.
>>>>>>>> + * @proto:  SPI protocol to use for the register operation.
>>>>>>>> + *
>>>>>>>> + * Return: zero on success, -errno otherwise
>>>>>>>> + */
>>>>>>>> +int spi_nor_write_reg(struct spi_nor *nor, struct spi_mem_op *op,
>>>>>>>> +                  enum spi_nor_protocol proto)
>>>>>>>> +{
>>>>>>>> +    int ret;
>>>>>>>> +
>>>>>>>> +    if (!nor->spimem)
>>>>>>>> +            return -EOPNOTSUPP;
>>>>>>>> +
>>>>>>>> +    ret = spi_nor_write_enable(nor);
>>>>>>>> +    if (ret)
>>>>>>>> +            return ret;
>>>>>>>> +    spi_nor_spimem_setup_op(nor, op, proto);
>>>>>>>> +    return spi_nor_spimem_exec_op(nor, op);
>>>>>>
>>>>>> After seeing your next two patches. Shouldn't the
>>>>>> spi_nor_wait_until_ready() call be here too?
>>>>>>
>>>>>
>>>>> I thought of this too, but seems that for a reason that I don't
>>>>> remember, we don't call for spi_nor_wait_until_ready after we
>>>>> write the octal DTR bit. Pratyush, do you remember why?
>>>>
>>>> We are not sure the protocol changed correctly so we can't rely on
>>>> spi_nor_wait_until_ready(). We read the ID instead to be sure.
>>>
>>> So besides the fact that the write_reg only works with the 'correct'
>>> op parameter, it is also tailored to the special use case. For real
>>> write_reg(), the user would actually has to poll the status bit
>>> afterwards? :(
>>>
>> Don't be sad :D. Are the octal DTR methods an exception?
>> If yes, let's add the call to spi_nor_wait_until_ready() in the
>> read/write_any_reg() methods, and let the octal methods handle
>> the specific write themselves, without calling for ready()
> 
> It has been a while, but IIRC I asked Cypress about this, because I was
> worried about reading ID while the switch to 8D mode was still in
> progress. They said that volatile register writes are instant and do not
> need any status polling. So the switch to 8D-8D-8D mode would be instant
> and there is no need to wait for anything.
> 
> The Cypress S28 flash datasheet does not say this explicitly. It does
> say that writing to non-volatile registers takes time and you need to
> wait for ready for those, but makes no mention of volatile registers. We
> don't ever want to write non-volatile registers so we can ignore that
> problem.
> 
> I see the Micron MT35 datasheet say this explicitly, that changes to
> volatile registers are instant.
> 
> So I would say that based on my limited sample size, volatile register
> writes for Cypress and Micron flashes do _not_ need
> spi_nor_wait_until_ready().

Thanks, Pratyush! I'll add a comment and/or update the commit message,
this is useful info.

Cheers,
ta

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

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

* Re: [PATCH v3 9/9] mtd: spi-nor: Introduce templates for SPI NOR operations
  2022-04-19 11:45     ` Michael Walle
@ 2022-04-20  7:49       ` Pratyush Yadav
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Yadav @ 2022-04-20  7:49 UTC (permalink / raw)
  To: Michael Walle
  Cc: Tudor Ambarus, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

On 19/04/22 01:45PM, Michael Walle wrote:
> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> > Clean the op declaration and hide the details of each op. With this it
> > results a cleanner, easier to read code. No functional change expected.
> > 
> > Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> 
> I haven't gone through all of it.

Same.

> 
> Acked-by: Michael Walle <michael@walle.cc>

Acked-by: Pratyush Yadav <p.yadav@ti.com>

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.

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

* Re: [PATCH v3 9/9] mtd: spi-nor: Introduce templates for SPI NOR operations
@ 2022-04-20  7:49       ` Pratyush Yadav
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Yadav @ 2022-04-20  7:49 UTC (permalink / raw)
  To: Michael Walle
  Cc: Tudor Ambarus, miquel.raynal, richard, vigneshr, linux-mtd,
	linux-kernel, nicolas.ferre

On 19/04/22 01:45PM, Michael Walle wrote:
> Am 2022-04-11 11:10, schrieb Tudor Ambarus:
> > Clean the op declaration and hide the details of each op. With this it
> > results a cleanner, easier to read code. No functional change expected.
> > 
> > Signed-off-by: Tudor Ambarus <tudor.ambarus@microchip.com>
> 
> I haven't gone through all of it.

Same.

> 
> Acked-by: Michael Walle <michael@walle.cc>

Acked-by: Pratyush Yadav <p.yadav@ti.com>

-- 
Regards,
Pratyush Yadav
Texas Instruments Inc.

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

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

end of thread, other threads:[~2022-04-20  7:50 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-11  9:10 [PATCH v3 0/9] mtd: spi-nor: Rework Octal DTR methods Tudor Ambarus
2022-04-11  9:10 ` Tudor Ambarus
2022-04-11  9:10 ` [PATCH v3 1/9] mtd: spi-nor: Rename method, s/spi_nor_match_id/spi_nor_match_name Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-11  9:10 ` [PATCH v3 2/9] mtd: spi-nor: Introduce spi_nor_match_id() Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-11  9:10 ` [PATCH v3 3/9] mtd: spi-nor: core: Use auto-detection only once Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-19 10:18   ` Michael Walle
2022-04-19 10:18     ` Michael Walle
2022-04-11  9:10 ` [PATCH v3 4/9] mtd: spi-nor: core: Introduce method for RDID op Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-19 11:10   ` Michael Walle
2022-04-19 11:10     ` Michael Walle
2022-04-11  9:10 ` [PATCH v3 5/9] mtd: spi-nor: manufacturers: Use spi_nor_read_id() core method Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-19 11:14   ` Michael Walle
2022-04-19 11:14     ` Michael Walle
2022-04-11  9:10 ` [PATCH v3 6/9] mtd: spi-nor: core: Add helpers to read/write any register Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-19 11:19   ` Michael Walle
2022-04-19 11:19     ` Michael Walle
2022-04-19 11:46     ` Michael Walle
2022-04-19 11:46       ` Michael Walle
2022-04-19 12:08       ` Tudor.Ambarus
2022-04-19 12:08         ` Tudor.Ambarus
2022-04-19 12:32         ` Pratyush Yadav
2022-04-19 12:32           ` Pratyush Yadav
2022-04-19 12:46           ` Michael Walle
2022-04-19 12:46             ` Michael Walle
2022-04-19 12:56             ` Tudor.Ambarus
2022-04-19 12:56               ` Tudor.Ambarus
2022-04-20  4:34               ` Pratyush Yadav
2022-04-20  4:34                 ` Pratyush Yadav
2022-04-20  5:20                 ` Takahiro Kuwano
2022-04-20  5:20                   ` Takahiro Kuwano
2022-04-20  5:25                 ` Tudor.Ambarus
2022-04-20  5:25                   ` Tudor.Ambarus
2022-04-19 13:02           ` Tudor.Ambarus
2022-04-19 13:02             ` Tudor.Ambarus
2022-04-19 12:59     ` Tudor.Ambarus
2022-04-19 12:59       ` Tudor.Ambarus
2022-04-11  9:10 ` [PATCH v3 7/9] mtd: spi-nor: micron-st: Rework spi_nor_micron_octal_dtr_enable() Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-19 11:43   ` Michael Walle
2022-04-19 11:43     ` Michael Walle
2022-04-11  9:10 ` [PATCH v3 8/9] mtd: spi-nor: spansion: Rework spi_nor_cypress_octal_dtr_enable() Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-19 11:44   ` Michael Walle
2022-04-19 11:44     ` Michael Walle
2022-04-11  9:10 ` [PATCH v3 9/9] mtd: spi-nor: Introduce templates for SPI NOR operations Tudor Ambarus
2022-04-11  9:10   ` Tudor Ambarus
2022-04-19 11:45   ` Michael Walle
2022-04-19 11:45     ` Michael Walle
2022-04-20  7:49     ` Pratyush Yadav
2022-04-20  7:49       ` Pratyush Yadav

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