[PATCH 3/4] mtd: spinand: Add support continuous read operation

Zhengxun zhengxunli.mxic at gmail.com
Thu Oct 7 23:57:58 PDT 2021


The patch adds a continuous read start flag to support continuous
read operations. The continuous read operation only issues a page
read command (13h), issues multiple read commands from the cache
(03h/0Bh/3Bh/6Bh/BBh/EBh) to read continuous address data, and
finally issues an exit continuous read command (63h) to terminate
this continuous read operation.

Since the continuous read mode can only read the entire page of data
(2KB) and cannot read the oob data, the dynamic change mode is added
to enable continuous read mode and disable continuous read mode in
spinand_mtd_read to avoid writing and erasing operation is abnormal.

Signed-off-by: Zhengxun <zhengxunli.mxic at gmail.com>
---
 drivers/mtd/nand/spi/core.c | 38 +++++++++++++++++++++++++++++---------
 include/linux/mtd/spinand.h |  2 ++
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c
index 0d9632f..0369453 100644
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -195,6 +195,8 @@ static int spinand_init_quad_enable(struct spinand_device *spinand)
 
 static int spinand_continuous_read_enable(struct spinand_device *spinand)
 {
+	spinand->cont_read_start = false;
+
 	if (!(spinand->flags & SPINAND_HAS_CONT_READ_BIT))
 		return 0;
 
@@ -598,16 +600,22 @@ static int spinand_read_page(struct spinand_device *spinand,
 	if (ret)
 		return ret;
 
-	ret = spinand_load_page_op(spinand, req);
-	if (ret)
-		return ret;
+	if (!spinand->cont_read_start) {
 
-	ret = spinand_wait(spinand,
-			   SPINAND_READ_INITIAL_DELAY_US,
-			   SPINAND_READ_POLL_DELAY_US,
-			   &status);
-	if (ret < 0)
-		return ret;
+		ret = spinand_load_page_op(spinand, req);
+		if (ret)
+			return ret;
+
+		ret = spinand_wait(spinand,
+				   SPINAND_READ_INITIAL_DELAY_US,
+				   SPINAND_READ_POLL_DELAY_US,
+				   &status);
+		if (ret < 0)
+			return ret;
+
+		if (spinand->flags & SPINAND_HAS_CONT_READ_BIT)
+			spinand->cont_read_start = true;
+	}
 
 	spinand_ondie_ecc_save_status(nand, status);
 
@@ -667,6 +675,10 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
 
 	mutex_lock(&spinand->lock);
 
+	ret = spinand_continuous_read_enable(spinand);
+	if (ret)
+		return ret;
+
 	nanddev_io_for_each_page(nand, NAND_PAGE_READ, from, ops, &iter) {
 		if (disable_ecc)
 			iter.req.mode = MTD_OPS_RAW;
@@ -689,6 +701,14 @@ static int spinand_mtd_read(struct mtd_info *mtd, loff_t from,
 		ops->oobretlen += iter.req.ooblen;
 	}
 
+	ret = spinand_continuous_read_exit(spinand);
+	if (ret)
+		return ret;
+
+	ret = spinand_continuous_read_disable(spinand);
+	if (ret)
+		return ret;
+
 	mutex_unlock(&spinand->lock);
 
 	if (ecc_failed && !ret)
diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h
index e044aba..c2a41a3 100644
--- a/include/linux/mtd/spinand.h
+++ b/include/linux/mtd/spinand.h
@@ -422,6 +422,7 @@ struct spinand_dirmap {
  *		because the spi-mem interface explicitly requests that buffers
  *		passed in spi_mem_op be DMA-able, so we can't based the bufs on
  *		the stack
+ * @cont_read_start: record the continuous read status
  * @manufacturer: SPI NAND manufacturer information
  * @priv: manufacturer private data
  */
@@ -450,6 +451,7 @@ struct spinand_device {
 	u8 *databuf;
 	u8 *oobbuf;
 	u8 *scratchbuf;
+	bool cont_read_start;
 	const struct spinand_manufacturer *manufacturer;
 	void *priv;
 };
-- 
2.7.4




More information about the linux-mtd mailing list