From 7b73a343cb3419cd542e70f3042502a7cb1b9671 Mon Sep 17 00:00:00 2001 From: Francois Ramu Date: Wed, 24 Jan 2024 12:55:47 +0100 Subject: [PATCH] drivers: flash: stm32 ospi driver aborts memmap before erase/write This change is aborting the memoryMapped mode of the octo-flash before erasing or writing the NOR. Operations are performed in command mode. Reading is always performed in MemoryMapped mode (memcopy) Signed-off-by: Francois Ramu --- drivers/flash/flash_stm32_ospi.c | 78 ++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/drivers/flash/flash_stm32_ospi.c b/drivers/flash/flash_stm32_ospi.c index 5a9f73fe7bf..e34c38e6eec 100644 --- a/drivers/flash/flash_stm32_ospi.c +++ b/drivers/flash/flash_stm32_ospi.c @@ -1018,7 +1018,7 @@ static int stm32_ospi_set_memorymap(const struct device *dev) HAL_OSPI_ADDRESS_24_BITS) ? SPI_NOR_CMD_READ_FAST : SPI_NOR_CMD_READ_FAST_4B) - : SPI_NOR_OCMD_RD) + : dev_data->read_opcode) : SPI_NOR_OCMD_DTR_RD; s_command.AddressMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) ? ((dev_cfg->data_mode == OSPI_SPI_MODE) @@ -1099,6 +1099,20 @@ static bool stm32_ospi_is_memorymap(const struct device *dev) OCTOSPI_CR_FMODE) == OCTOSPI_CR_FMODE) ? true : false); } + +static int stm32_ospi_abort(const struct device *dev) +{ + struct flash_stm32_ospi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_OSPI_Abort(&dev_data->hospi); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: OSPI abort failed", hal_ret); + return -EIO; + } + + return 0; +} #endif /* CONFIG_STM32_MEMMAP */ /* @@ -1136,11 +1150,18 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, return -ENOTSUP; } + ospi_lock_thread(dev); + #ifdef CONFIG_STM32_MEMMAP if (stm32_ospi_is_memorymap(dev)) { - LOG_DBG("MemoryMap : cannot erase"); - return 0; + /* Abort ongoing transfer to force CS high/BUSY deasserted */ + ret = stm32_ospi_abort(dev); + if (ret != 0) { + LOG_ERR("Failed to abort memory-mapped access before erase"); + goto end_erase; + } } + /* Continue with Indirect Mode */ #endif /* CONFIG_STM32_MEMMAP */ OSPI_RegularCmdTypeDef cmd_erase = { @@ -1153,8 +1174,6 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, .SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD, }; - ospi_lock_thread(dev); - if (stm32_ospi_mem_ready(dev_data, dev_cfg->data_mode, dev_cfg->data_rate) != 0) { LOG_ERR("Erase failed : flash busy"); @@ -1265,8 +1284,8 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, ret = stm32_ospi_mem_ready(dev_data, dev_cfg->data_mode, dev_cfg->data_rate); } - } + goto end_erase; end_erase: ospi_unlock_thread(dev); @@ -1278,9 +1297,7 @@ end_erase: static int flash_stm32_ospi_read(const struct device *dev, off_t addr, void *data, size_t size) { - const struct flash_stm32_ospi_config *dev_cfg = dev->config; - struct flash_stm32_ospi_data *dev_data = dev->data; - int ret; + int ret = 0; if (!ospi_address_is_valid(dev, addr, size)) { LOG_ERR("Error: address or size exceeds expected values: " @@ -1294,15 +1311,23 @@ static int flash_stm32_ospi_read(const struct device *dev, off_t addr, } #ifdef CONFIG_STM32_MEMMAP - if (stm32_ospi_is_memorymap(dev)) { - LOG_DBG("MemoryMapped Read offset: 0x%lx, len: %zu", - (long)(STM32_OSPI_BASE_ADDRESS + addr), - size); - memcpy(data, (uint8_t *)STM32_OSPI_BASE_ADDRESS + addr, size); - - return 0; + /* If not MemMapped then configure it */ + if (!stm32_ospi_is_memorymap(dev)) { + if (stm32_ospi_set_memorymap(dev) != 0) { + LOG_ERR("READ failed: cannot enable MemoryMap"); + return -EIO; + } } -#endif /* CONFIG_STM32_MEMMAP */ + /* Now in MemMapped mode : read with memcopy */ + LOG_DBG("MemoryMapped Read offset: 0x%lx, len: %zu", + (long)(STM32_OSPI_BASE_ADDRESS + addr), + size); + memcpy(data, (uint8_t *)STM32_OSPI_BASE_ADDRESS + addr, size); + +#else /* CONFIG_STM32_MEMMAP */ + const struct flash_stm32_ospi_config *dev_cfg = dev->config; + struct flash_stm32_ospi_data *dev_data = dev->data; + OSPI_RegularCmdTypeDef cmd = ospi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); @@ -1369,6 +1394,7 @@ static int flash_stm32_ospi_read(const struct device *dev, off_t addr, ospi_unlock_thread(dev); +#endif /* CONFIG_STM32_MEMMAP */ return ret; } @@ -1395,15 +1421,18 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, return 0; } + ospi_lock_thread(dev); + #ifdef CONFIG_STM32_MEMMAP if (stm32_ospi_is_memorymap(dev)) { - LOG_DBG("MemoryMapped Write offset: 0x%lx, len: %zu", - (long)(STM32_OSPI_BASE_ADDRESS + addr), - size); - memcpy((uint8_t *)STM32_OSPI_BASE_ADDRESS + addr, data, size); - - return 0; + /* Abort ongoing transfer to force CS high/BUSY deasserted */ + ret = stm32_ospi_abort(dev); + if (ret != 0) { + LOG_ERR("Failed to abort memory-mapped access before write"); + goto end_write; + } } + /* Continue with Indirect Mode */ #endif /* CONFIG_STM32_MEMMAP */ /* page program for STR or DTR mode */ OSPI_RegularCmdTypeDef cmd_pp = ospi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); @@ -1448,7 +1477,6 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, cmd_pp.DummyCycles = 0U; LOG_DBG("OSPI: write %zu data", size); - ospi_lock_thread(dev); ret = stm32_ospi_mem_ready(dev_data, dev_cfg->data_mode, dev_cfg->data_rate); @@ -1497,7 +1525,9 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, break; } } + goto end_write; +end_write: ospi_unlock_thread(dev); return ret;