public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Sean Anderson <seanga2@gmail.com>
To: u-boot@lists.denx.de
Subject: [RFC PATCH 03/13] mtd: spi-nor: use spi-mem dirmap API
Date: Thu,  4 Feb 2021 23:39:13 -0500	[thread overview]
Message-ID: <20210205043924.149504-4-seanga2@gmail.com> (raw)
In-Reply-To: <20210205043924.149504-1-seanga2@gmail.com>

This adds support for the dirmap API to the spi-nor subsystem, as
introduced in Linux commit df5c21002cf4 ("mtd: spi-nor: use spi-mem dirmap
API").

Signed-off-by: Sean Anderson <seanga2@gmail.com>
---

 drivers/mtd/spi/sf_probe.c     | 79 ++++++++++++++++++++++++++++++++++
 drivers/mtd/spi/spi-nor-core.c | 45 +++++++++++++------
 include/linux/mtd/spi-nor.h    |  6 +++
 3 files changed, 116 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 6c87434867..796a2fa6bc 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -14,9 +14,72 @@
 #include <malloc.h>
 #include <spi.h>
 #include <spi_flash.h>
+#include <spi-mem.h>
 
 #include "sf_internal.h"
 
+#if CONFIG_IS_ENABLED(SPI_DIRMAP)
+static int spi_nor_create_read_dirmap(struct spi_nor *nor)
+{
+	struct spi_mem_dirmap_info info = {
+		.op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 1),
+				      SPI_MEM_OP_ADDR(nor->addr_width, 0, 1),
+				      SPI_MEM_OP_DUMMY(nor->read_dummy, 1),
+				      SPI_MEM_OP_DATA_IN(0, NULL, 1)),
+		.offset = 0,
+		.length = nor->mtd.size,
+	};
+	struct spi_mem_op *op = &info.op_tmpl;
+
+	/* get transfer protocols. */
+	op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->read_proto);
+	op->addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->read_proto);
+	op->dummy.buswidth = op->addr.buswidth;
+	op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->read_proto);
+
+	/* convert the dummy cycles to the number of bytes */
+	op->dummy.nbytes = (nor->read_dummy * op->dummy.buswidth) / 8;
+
+	nor->dirmap.rdesc = spi_mem_dirmap_create(nor->spi, &info);
+	return PTR_ERR_OR_ZERO(nor->dirmap.rdesc);
+}
+
+static int spi_nor_create_write_dirmap(struct spi_nor *nor)
+{
+	struct spi_mem_dirmap_info info = {
+		.op_tmpl = SPI_MEM_OP(SPI_MEM_OP_CMD(nor->program_opcode, 1),
+				      SPI_MEM_OP_ADDR(nor->addr_width, 0, 1),
+				      SPI_MEM_OP_NO_DUMMY,
+				      SPI_MEM_OP_DATA_OUT(0, NULL, 1)),
+		.offset = 0,
+		.length = nor->mtd.size,
+	};
+	struct spi_mem_op *op = &info.op_tmpl;
+
+	/* get transfer protocols. */
+	op->cmd.buswidth = spi_nor_get_protocol_inst_nbits(nor->write_proto);
+	op->addr.buswidth = spi_nor_get_protocol_addr_nbits(nor->write_proto);
+	op->dummy.buswidth = op->addr.buswidth;
+	op->data.buswidth = spi_nor_get_protocol_data_nbits(nor->write_proto);
+
+	if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
+		op->addr.nbytes = 0;
+
+	nor->dirmap.wdesc = spi_mem_dirmap_create(nor->spi, &info);
+	return PTR_ERR_OR_ZERO(nor->dirmap.wdesc);
+}
+#else
+static int spi_nor_create_read_dirmap(struct spi_nor *nor)
+{
+	return 0;
+}
+
+static int spi_nor_create_write_dirmap(struct spi_nor *nor)
+{
+	return 0;
+}
+#endif /* CONFIG_SPI_DIRMAP */
+
 /**
  * spi_flash_probe_slave() - Probe for a SPI flash device on a bus
  *
@@ -45,6 +108,14 @@ static int spi_flash_probe_slave(struct spi_flash *flash)
 	if (ret)
 		goto err_read_id;
 
+	ret = spi_nor_create_read_dirmap(flash);
+	if (ret)
+		return ret;
+
+	ret = spi_nor_create_write_dirmap(flash);
+	if (ret)
+		return ret;
+
 	if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
 		ret = spi_flash_mtd_register(flash);
 
@@ -83,6 +154,9 @@ struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs,
 
 void spi_flash_free(struct spi_flash *flash)
 {
+	spi_mem_dirmap_destroy(flash->dirmap.wdesc);
+	spi_mem_dirmap_destroy(flash->dirmap.rdesc);
+
 	if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
 		spi_flash_mtd_unregister();
 
@@ -143,6 +217,11 @@ int spi_flash_std_probe(struct udevice *dev)
 
 static int spi_flash_std_remove(struct udevice *dev)
 {
+	struct spi_flash *flash = dev_get_uclass_priv(dev);
+
+	spi_mem_dirmap_destroy(flash->dirmap.wdesc);
+	spi_mem_dirmap_destroy(flash->dirmap.rdesc);
+
 	if (CONFIG_IS_ENABLED(SPI_FLASH_MTD))
 		spi_flash_mtd_unregister();
 
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index e16b0e1462..32c712a9f1 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -96,13 +96,23 @@ static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
 
 	while (remaining) {
 		op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
-		ret = spi_mem_adjust_op_size(nor->spi, &op);
-		if (ret)
-			return ret;
 
-		ret = spi_mem_exec_op(nor->spi, &op);
-		if (ret)
-			return ret;
+		if (CONFIG_IS_ENABLED(SPI_DIRMAP) && nor->dirmap.rdesc) {
+			ret = spi_mem_dirmap_read(nor->dirmap.rdesc,
+						  op.addr.val, op.data.nbytes,
+						  op.data.buf.in);
+			if (ret < 0)
+				return ret;
+			op.data.nbytes = ret;
+		} else {
+			ret = spi_mem_adjust_op_size(nor->spi, &op);
+			if (ret)
+				return ret;
+
+			ret = spi_mem_exec_op(nor->spi, &op);
+			if (ret)
+				return ret;
+		}
 
 		op.addr.val += op.data.nbytes;
 		remaining -= op.data.nbytes;
@@ -120,6 +130,7 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
 				   SPI_MEM_OP_ADDR(nor->addr_width, to, 1),
 				   SPI_MEM_OP_NO_DUMMY,
 				   SPI_MEM_OP_DATA_OUT(len, buf, 1));
+	ssize_t nbytes;
 	int ret;
 
 	/* get transfer protocols. */
@@ -130,16 +141,22 @@ static ssize_t spi_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
 	if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
 		op.addr.nbytes = 0;
 
-	ret = spi_mem_adjust_op_size(nor->spi, &op);
-	if (ret)
-		return ret;
-	op.data.nbytes = len < op.data.nbytes ? len : op.data.nbytes;
+	if (CONFIG_IS_ENABLED(SPI_DIRMAP) && nor->dirmap.wdesc) {
+		nbytes = spi_mem_dirmap_write(nor->dirmap.wdesc, op.addr.val,
+					      op.data.nbytes, op.data.buf.out);
+	} else {
+		ret = spi_mem_adjust_op_size(nor->spi, &op);
+		if (ret)
+			return ret;
+		op.data.nbytes = len < op.data.nbytes ? len : op.data.nbytes;
 
-	ret = spi_mem_exec_op(nor->spi, &op);
-	if (ret)
-		return ret;
+		ret = spi_mem_exec_op(nor->spi, &op);
+		if (ret)
+			return ret;
+		nbytes = op.data.nbytes;
+	}
 
-	return op.data.nbytes;
+	return nbytes;
 }
 
 /*
diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
index 39ef872ebf..ffa4dd3e7d 100644
--- a/include/linux/mtd/spi-nor.h
+++ b/include/linux/mtd/spi-nor.h
@@ -304,6 +304,7 @@ struct spi_flash {
  * @flash_is_locked:	[FLASH-SPECIFIC] check if a region of the SPI NOR is
  *			completely locked
  * @quad_enable:	[FLASH-SPECIFIC] enables SPI NOR quad mode
+ * @dirmap:             pointers to struct spi_mem_dirmap_desc for reads/writes.
  * @priv:		the private data
  */
 struct spi_nor {
@@ -346,6 +347,11 @@ struct spi_nor {
 	int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);
 	int (*quad_enable)(struct spi_nor *nor);
 
+	struct {
+		struct spi_mem_dirmap_desc *rdesc;
+		struct spi_mem_dirmap_desc *wdesc;
+	} dirmap;
+
 	void *priv;
 /* Compatibility for spi_flash, remove once sf layer is merged with mtd */
 	const char *name;
-- 
2.29.2

  parent reply	other threads:[~2021-02-05  4:39 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-05  4:39 [RFC PATCH 00/13] spi: dw: Add support for XIP mode Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 01/13] linux err: Synchronize with Linux 5.10 Sean Anderson
2021-02-07 14:37   ` Simon Glass
2021-02-05  4:39 ` [RFC PATCH 02/13] spi-mem: Add dirmap API from Linux Sean Anderson
2021-02-05  4:39 ` Sean Anderson [this message]
2021-02-05  4:39 ` [RFC PATCH 04/13] core: ofnode: Fix inconsistent returns of *_read_u32_array Sean Anderson
2021-02-07 14:37   ` Simon Glass
2021-02-05  4:39 ` [RFC PATCH 05/13] mux: Inline mux functions when CONFIG_MUX is disabled Sean Anderson
2021-02-05  7:32   ` Pratyush Yadav
2021-02-05  4:39 ` [RFC PATCH 06/13] mux: Define a stub for mux_get_by_index if " Sean Anderson
2021-02-05 10:53   ` Pratyush Yadav
2021-02-05  4:39 ` [RFC PATCH 07/13] mux: mmio: Only complain about idle-states if it is malformed Sean Anderson
2021-02-05 11:06   ` Pratyush Yadav
2021-02-05 13:28     ` Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 08/13] spi: dw: Define XIP registers Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 09/13] spi: dw: Add XIP and XIP_CONCURRENT caps Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 10/13] spi: dw: Use a mux to access registers Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 11/13] spi: dw: Add support for DIRMAP Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 12/13] riscv: k210: Increase SPI3 bus clock to CPU speed Sean Anderson
2021-02-05  4:39 ` [RFC PATCH 13/13] riscv: k210: Add bindings for SPI XIP Sean Anderson
2021-02-05  4:43 ` [RFC PATCH 00/13] spi: dw: Add support for XIP mode Sean Anderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210205043924.149504-4-seanga2@gmail.com \
    --to=seanga2@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox