@@ -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
@@ -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;
@@ -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;
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(-)