[PATCH 1/2] mtd: spi-nor: core: Add a helper to read with alternative method

tkuw584924 at gmail.com tkuw584924 at gmail.com
Fri Aug 12 01:06:32 PDT 2022


From: Takahiro Kuwano <Takahiro.Kuwano at infineon.com>

The existing spi_nor_read_data() uses preset opcode, number of address
bytes, and dummy cycles. During SFDP parse and corresponding fixups we
need to perform read op with different opcode, number of address, and/or
dummy cycles from preset ones. The spi_nor_alt_read() helps that by
backup - read op - restore the preset opcode, etc.

Signed-off-by: Takahiro Kuwano <Takahiro.Kuwano at infineon.com>
---
 drivers/mtd/spi-nor/core.c | 48 ++++++++++++++++++++++++++++++++++++++
 drivers/mtd/spi-nor/core.h |  2 ++
 2 files changed, 50 insertions(+)

diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c
index f2c64006f8d7..ae98b4ad9b19 100644
--- a/drivers/mtd/spi-nor/core.c
+++ b/drivers/mtd/spi-nor/core.c
@@ -247,6 +247,54 @@ ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len, u8 *buf)
 	return nor->controller_ops->read(nor, from, len, buf);
 }
 
+/**
+ * spi_nor_alt_read() - read data from flash memory with alternative opcode,
+ *                      number of address bytes, and dummy cycles.
+ * @nor:		pointer to 'struct spi_nor'
+ * @from:		offset to read from
+ * @len:		number of bytes to read
+ * @buf:		pointer to dst buffer
+ * @read_opcode:	read opcode to issue
+ * @addr_nbytes:	number of address bytes to send
+ * @read_dummy:		number of dummy cycles needed to read
+ *
+ * Return: 0 on success, -errno otherwise
+ */
+int spi_nor_alt_read(struct spi_nor *nor, u32 addr, size_t len, u8 *buf,
+		     u8 read_opcode, u8 addr_nbytes, u8 read_dummy)
+{
+	u8 bak_read_opcode = nor->read_opcode;
+	u8 bak_addr_nbytes = nor->addr_nbytes;
+	u8 bak_read_dummy = nor->read_dummy;
+	ssize_t ret;
+
+	nor->read_opcode = read_opcode;
+	nor->addr_nbytes = addr_nbytes;
+	nor->read_dummy = read_dummy;
+
+	while (len) {
+		ret = spi_nor_read_data(nor, addr, len, buf);
+		if (ret < 0)
+			goto out;
+		if (!ret || ret > len) {
+			ret = -EIO;
+			goto out;
+		}
+
+		buf += ret;
+		addr += ret;
+		len -= ret;
+	}
+	ret = 0;
+
+out:
+	nor->read_opcode = bak_read_opcode;
+	nor->addr_nbytes = bak_addr_nbytes;
+	nor->read_dummy = bak_read_dummy;
+
+	return ret;
+}
+
 /**
  * spi_nor_spimem_write_data() - write data to flash memory via
  *                               spi-mem
diff --git a/drivers/mtd/spi-nor/core.h b/drivers/mtd/spi-nor/core.h
index 85b0cf254e97..4f1e636f9362 100644
--- a/drivers/mtd/spi-nor/core.h
+++ b/drivers/mtd/spi-nor/core.h
@@ -656,6 +656,8 @@ 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_alt_read(struct spi_nor *nor, u32 addr, size_t len, u8 *buf,
+		     u8 read_opcode, u8 addr_nbytes, u8 read_dummy);
 int spi_nor_read_any_reg(struct spi_nor *nor, struct spi_mem_op *op,
 			 enum spi_nor_protocol proto);
 int spi_nor_write_any_volatile_reg(struct spi_nor *nor, struct spi_mem_op *op,
-- 
2.25.1




More information about the linux-mtd mailing list