[PATCH v2 2/2] spi: allow calling WATCHDOG_RESET during long reads
Rasmus Villemoes
rasmus.villemoes at prevas.dk
Fri Mar 20 11:14:48 CET 2020
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 at 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 --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;
--
2.23.0
More information about the U-Boot
mailing list