From 41c33d7f32658d0e0f80af11ad7817e8893ff55e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20G=C5=82=C4=85bek?= Date: Thu, 13 Jul 2023 08:57:48 +0200 Subject: [PATCH] drivers: flash: nrf_qspi_nor: Fix writing from unaligned RAM buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flash API states that drivers should support write requests without any restrictions on location or alignment of the source buffer. Due to hardware limitations of the QSPI peripheral, the nrf_qspi_nor driver currently fails to perform a write from a RAM buffer that is not word-aligned. Fix this by using in such case the same mechanism that is used when the source buffer is located in the internal flash (copy data to a buffer located on stack). Also correct the length parameter for writes from this stack-based buffer to be the actual data chunk length, not always the size of the buffer (as for CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE > 4 this may lead to overwriting of some data located next in the flash). Signed-off-by: Andrzej Głąbek --- drivers/flash/Kconfig.nordic_qspi_nor | 15 ++++++++------- drivers/flash/nrf_qspi_nor.c | 11 ++++++----- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/flash/Kconfig.nordic_qspi_nor b/drivers/flash/Kconfig.nordic_qspi_nor index ca0058e6aed..16252e0812c 100644 --- a/drivers/flash/Kconfig.nordic_qspi_nor +++ b/drivers/flash/Kconfig.nordic_qspi_nor @@ -28,14 +28,15 @@ config NORDIC_QSPI_NOR_FLASH_LAYOUT_PAGE_SIZE size (65536). Other option include the sector size (4096). config NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE - int "Size of a stack-based buffer to support writes from NVMC" + int "Size of a stack-based buffer to handle writes not supported by QSPI" default 4 help - The QSPI peripheral uses DMA and cannot write data that is - read from the internal flash. A non-zero value here enables - a stack buffer into which data is copied to allow the write - to proceed. Multiple transfers will be initiated if the - data is larger than the configured limit. Must be a - multiple of 4. The feature is disabled when set to 0. + The QSPI peripheral uses DMA and can only write data that is read + from a word-aligned location in RAM. A non-zero value here enables + a stack buffer to be used for any source data that does not meet + these restrictions. Such data will be copied into this buffer to + allow the write to proceed. Multiple transfers will be initiated + if the data is larger than the configured size. + Must be a multiple of 4. When set to 0, the feature is disabled. endif # NORDIC_QSPI_NOR diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index facd37fb304..2986c819e0f 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -1060,8 +1060,8 @@ BUILD_ASSERT((CONFIG_NORDIC_QSPI_NOR_STACK_WRITE_BUFFER_SIZE % 4) == 0, * * If not enabled return the error the peripheral would have produced. */ -static inline nrfx_err_t write_from_nvmc(const struct device *dev, off_t addr, - const void *sptr, size_t slen) +static nrfx_err_t write_through_buffer(const struct device *dev, off_t addr, + const void *sptr, size_t slen) { nrfx_err_t res = NRFX_SUCCESS; @@ -1073,7 +1073,7 @@ static inline nrfx_err_t write_from_nvmc(const struct device *dev, off_t addr, size_t len = MIN(slen, sizeof(buf)); memcpy(buf, sp, len); - res = nrfx_qspi_write(buf, sizeof(buf), addr); + res = nrfx_qspi_write(buf, len, addr); qspi_wait_for_completion(dev, res); if (res == NRFX_SUCCESS) { @@ -1131,8 +1131,9 @@ static int qspi_nor_write(const struct device *dev, off_t addr, if (!res) { if (size < 4U) { res = write_sub_word(dev, addr, src, size); - } else if (!nrfx_is_in_ram(src)) { - res = write_from_nvmc(dev, addr, src, size); + } else if (!nrfx_is_in_ram(src) || + !nrfx_is_word_aligned(src)) { + res = write_through_buffer(dev, addr, src, size); } else { res = nrfx_qspi_write(src, size, addr); qspi_wait_for_completion(dev, res);