diff mbox series

[v2,2/2] spi: allow calling WATCHDOG_RESET during long reads

Message ID 20200320101448.10714-2-rasmus.villemoes@prevas.dk
State Changes Requested
Delegated to: Jagannadha Sutradharudu Teki
Headers show
Series [v2,1/2] spi: call WATCHDOG_RESET() in spi_nor_wait_till_ready_with_timeout() | expand

Commit Message

Rasmus Villemoes March 20, 2020, 10:14 a.m. UTC
Some boards have a watchdog with a short (~1s) timeout and a slowish
nor flash. For example, I'm currently working on a board where doing a
2MB read from the flash will cause the board to reset.

Similar to the various CHUNKSZ, CHUNKSZ_SHA1 etc. defines that are
used to chop hash digest and/or memmove operations into chunks, doing
a WATCHDOG_RESET for each, introduce a CONFIG_SPI_FLASH_READ_CHUNKSZ
config knob. We keep the default of doing the whole read in one go,
but the board config can set a suitable threshold.

Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
---
 drivers/mtd/spi/Kconfig        | 12 ++++++++++++
 drivers/mtd/spi/spi-nor-core.c |  4 +++-
 drivers/mtd/spi/spi-nor-tiny.c |  4 +++-
 3 files changed, 18 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index 018e8c597e..9dda0047d2 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -169,6 +169,18 @@  config SPI_FLASH_USE_4K_SECTORS
 	  Please note that some tools/drivers/filesystems may not work with
 	  4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum).
 
+config SPI_FLASH_READ_CHUNKSZ
+	int "Chunk size for reading from SPI flash"
+	depends on SPI_FLASH
+	default 0
+	help
+	  Some boards have a watchdog with a very short timeout
+	  period. Doing large reads from a SPI flash on such a board
+	  causes the watchdog to fire and reset the board. Setting
+	  this option to a non-zero value will ensure that
+	  watchdog_reset() gets called after each read of that many
+	  bytes.
+
 config SPI_FLASH_DATAFLASH
 	bool "AT45xxx DataFlash support"
 	depends on SPI_FLASH && DM_SPI_FLASH
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index c5d98debf0..8c846a4b42 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -82,6 +82,7 @@  static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
 				   SPI_MEM_OP_DUMMY(nor->read_dummy, 1),
 				   SPI_MEM_OP_DATA_IN(len, buf, 1));
 	size_t remaining = len;
+	size_t chunksz = CONFIG_SPI_FLASH_READ_CHUNKSZ ?: UINT_MAX;
 	int ret;
 
 	/* get transfer protocols. */
@@ -94,7 +95,7 @@  static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
 	op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
 
 	while (remaining) {
-		op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
+		op.data.nbytes = min(remaining, chunksz);
 		ret = spi_mem_adjust_op_size(nor->spi, &op);
 		if (ret)
 			return ret;
@@ -102,6 +103,7 @@  static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
 		ret = spi_mem_exec_op(nor->spi, &op);
 		if (ret)
 			return ret;
+		WATCHDOG_RESET();
 
 		op.addr.val += op.data.nbytes;
 		remaining -= op.data.nbytes;
diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c
index d91989567d..e9d490ba52 100644
--- a/drivers/mtd/spi/spi-nor-tiny.c
+++ b/drivers/mtd/spi/spi-nor-tiny.c
@@ -81,6 +81,7 @@  static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
 				   SPI_MEM_OP_DUMMY(nor->read_dummy, 1),
 				   SPI_MEM_OP_DATA_IN(len, buf, 1));
 	size_t remaining = len;
+	size_t chunksz = CONFIG_SPI_FLASH_READ_CHUNKSZ ?: UINT_MAX;
 	int ret;
 
 	/* get transfer protocols. */
@@ -93,7 +94,7 @@  static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
 	op.dummy.nbytes = (nor->read_dummy * op.dummy.buswidth) / 8;
 
 	while (remaining) {
-		op.data.nbytes = remaining < UINT_MAX ? remaining : UINT_MAX;
+		op.data.nbytes = min(remaining, chunksz);
 		ret = spi_mem_adjust_op_size(nor->spi, &op);
 		if (ret)
 			return ret;
@@ -101,6 +102,7 @@  static ssize_t spi_nor_read_data(struct spi_nor *nor, loff_t from, size_t len,
 		ret = spi_mem_exec_op(nor->spi, &op);
 		if (ret)
 			return ret;
+		WATCHDOG_RESET();
 
 		op.addr.val += op.data.nbytes;
 		remaining -= op.data.nbytes;