drivers: flash: stm32 ospi drivers with Memorymapped mode

Enable the MemoryMapped Mode for the stm32 octoFlash driver
Configure the Flash in MemoryMapped to use in XiP mode.
With this mode the erase and write are not supported.
Address and size are given by the DTS register property.

Signed-off-by: Francois Ramu <francois.ramu@st.com>
This commit is contained in:
Francois Ramu 2023-06-01 15:39:02 +02:00 committed by David Leach
commit 7593a14a0a

View file

@ -978,11 +978,135 @@ static int stm32_ospi_mem_reset(const struct device *dev)
return 0;
}
#ifdef CONFIG_STM32_MEMMAP
/* Function to configure the octoflash in MemoryMapped mode */
static int stm32_ospi_set_memorymap(const struct device *dev)
{
HAL_StatusTypeDef ret;
const struct flash_stm32_ospi_config *dev_cfg = dev->config;
struct flash_stm32_ospi_data *dev_data = dev->data;
OSPI_RegularCmdTypeDef s_command;
OSPI_MemoryMappedTypeDef s_MemMappedCfg;
/* Configure octoflash in MemoryMapped mode */
if ((dev_cfg->data_mode == OSPI_SPI_MODE) &&
(stm32_ospi_hal_address_size(dev) == HAL_OSPI_ADDRESS_24_BITS)) {
/* OPI mode and 3-bytes address size not supported by memory */
LOG_ERR("OSPI_SPI_MODE in 3Bytes addressing is not supported");
return -EIO;
}
/* Initialize the read command */
s_command.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
s_command.FlashId = HAL_OSPI_FLASH_ID_1;
s_command.InstructionMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? ((dev_cfg->data_mode == OSPI_SPI_MODE)
? HAL_OSPI_INSTRUCTION_1_LINE
: HAL_OSPI_INSTRUCTION_8_LINES)
: HAL_OSPI_INSTRUCTION_8_LINES;
s_command.InstructionDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? HAL_OSPI_INSTRUCTION_DTR_DISABLE
: HAL_OSPI_INSTRUCTION_DTR_ENABLE;
s_command.InstructionSize = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? ((dev_cfg->data_mode == OSPI_SPI_MODE)
? HAL_OSPI_INSTRUCTION_8_BITS
: HAL_OSPI_INSTRUCTION_16_BITS)
: HAL_OSPI_INSTRUCTION_16_BITS;
s_command.Instruction = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? ((dev_cfg->data_mode == OSPI_SPI_MODE)
? ((stm32_ospi_hal_address_size(dev) ==
HAL_OSPI_ADDRESS_24_BITS)
? SPI_NOR_CMD_READ_FAST
: SPI_NOR_CMD_READ_FAST_4B)
: SPI_NOR_OCMD_RD)
: SPI_NOR_OCMD_DTR_RD;
s_command.AddressMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? ((dev_cfg->data_mode == OSPI_SPI_MODE)
? HAL_OSPI_ADDRESS_1_LINE
: HAL_OSPI_ADDRESS_8_LINES)
: HAL_OSPI_ADDRESS_8_LINES;
s_command.AddressDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? HAL_OSPI_ADDRESS_DTR_DISABLE
: HAL_OSPI_ADDRESS_DTR_ENABLE;
s_command.AddressSize = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? stm32_ospi_hal_address_size(dev)
: HAL_OSPI_ADDRESS_32_BITS;
s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
s_command.DataMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? ((dev_cfg->data_mode == OSPI_SPI_MODE)
? HAL_OSPI_DATA_1_LINE
: HAL_OSPI_DATA_8_LINES)
: HAL_OSPI_DATA_8_LINES;
s_command.DataDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? HAL_OSPI_DATA_DTR_DISABLE
: HAL_OSPI_DATA_DTR_ENABLE;
s_command.DummyCycles = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? ((dev_cfg->data_mode == OSPI_SPI_MODE)
? SPI_NOR_DUMMY_RD
: SPI_NOR_DUMMY_RD_OCTAL)
: SPI_NOR_DUMMY_RD_OCTAL_DTR;
s_command.DQSMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER)
? HAL_OSPI_DQS_DISABLE
: HAL_OSPI_DQS_ENABLE;
s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
ret = HAL_OSPI_Command(&dev_data->hospi, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
if (ret != HAL_OK) {
LOG_ERR("%d: Failed to set memory map", ret);
return -EIO;
}
/* Initialize the program command */
s_command.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
if (dev_cfg->data_rate == OSPI_STR_TRANSFER) {
s_command.Instruction = (dev_cfg->data_mode == OSPI_SPI_MODE)
? ((stm32_ospi_hal_address_size(dev) ==
HAL_OSPI_ADDRESS_24_BITS)
? SPI_NOR_CMD_PP
: SPI_NOR_CMD_PP_4B)
: SPI_NOR_OCMD_PAGE_PRG;
} else {
s_command.Instruction = SPI_NOR_OCMD_PAGE_PRG;
}
s_command.DQSMode = HAL_OSPI_DQS_DISABLE;
ret = HAL_OSPI_Command(&dev_data->hospi, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
if (ret != HAL_OK) {
LOG_ERR("%d: Failed to set memory mapped", ret);
return -EIO;
}
/* Enable the memory-mapping */
s_MemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;
ret = HAL_OSPI_MemoryMapped(&dev_data->hospi, &s_MemMappedCfg);
if (ret != HAL_OK) {
LOG_ERR("%d: Failed to set memory mapped", ret);
return -EIO;
}
LOG_INF("MemoryMap mode enabled");
return 0;
}
/* Function to return true if the octoflash is in MemoryMapped else false */
static bool stm32_ospi_is_memorymap(const struct device *dev)
{
struct flash_stm32_ospi_data *dev_data = dev->data;
return ((READ_BIT(dev_data->hospi.Instance->CR,
OCTOSPI_CR_FMODE) == OCTOSPI_CR_FMODE) ?
true : false);
}
#endif /* CONFIG_STM32_MEMMAP */
/*
* Function to erase the flash : chip or sector with possible OSPI/SPI and STR/DTR
* to erase the complete chip (using dedicated command) :
* set size >= flash size
* set addr = 0
* NOTE: cannot erase in MemoryMapped mode
*/
static int flash_stm32_ospi_erase(const struct device *dev, off_t addr,
size_t size)
@ -1012,6 +1136,13 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr,
return -ENOTSUP;
}
#ifdef CONFIG_STM32_MEMMAP
if (stm32_ospi_is_memorymap(dev)) {
LOG_DBG("MemoryMap : cannot erase");
return 0;
}
#endif /* CONFIG_STM32_MEMMAP */
OSPI_RegularCmdTypeDef cmd_erase = {
.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG,
.FlashId = HAL_OSPI_FLASH_ID_1,
@ -1026,9 +1157,9 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr,
if (stm32_ospi_mem_ready(dev_data,
dev_cfg->data_mode, dev_cfg->data_rate) != 0) {
ospi_unlock_thread(dev);
LOG_ERR("Erase failed : flash busy");
return -EBUSY;
ret = -EBUSY;
goto end_erase;
}
cmd_erase.InstructionMode = (dev_cfg->data_mode == OSPI_OPI_MODE)
@ -1137,6 +1268,7 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr,
}
end_erase:
ospi_unlock_thread(dev);
return ret;
@ -1161,6 +1293,17 @@ static int flash_stm32_ospi_read(const struct device *dev, off_t addr,
return 0;
}
#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;
}
#endif /* CONFIG_STM32_MEMMAP */
OSPI_RegularCmdTypeDef cmd = ospi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate);
if (dev_cfg->data_mode != OSPI_OPI_MODE) {
@ -1229,7 +1372,10 @@ static int flash_stm32_ospi_read(const struct device *dev, off_t addr,
return ret;
}
/* Function to write the flash (page program) : with possible OSPI/SPI and STR/DTR */
/*
* Function to write the flash (page program) : with possible OSPI/SPI and STR/DTR
* NOTE: writing in MemoryMapped mode is not guaranted
*/
static int flash_stm32_ospi_write(const struct device *dev, off_t addr,
const void *data, size_t size)
{
@ -1249,6 +1395,16 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr,
return 0;
}
#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;
}
#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);
@ -1913,6 +2069,16 @@ static int flash_stm32_ospi_init(const struct device *dev)
return -ENODEV;
}
#ifdef CONFIG_STM32_MEMMAP
/* If MemoryMapped then configure skip init */
if (stm32_ospi_is_memorymap(dev)) {
LOG_DBG("NOR init'd in MemMapped mode\n");
/* Force HAL instance in correct state */
dev_data->hospi.State = HAL_OSPI_STATE_BUSY_MEM_MAPPED;
return 0;
}
#endif /* CONFIG_STM32_MEMMAP */
#if STM32_OSPI_USE_DMA
/*
* DMA configuration
@ -2292,9 +2458,21 @@ static int flash_stm32_ospi_init(const struct device *dev)
}
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
LOG_INF("NOR octo-flash at 0x%lx (0x%x bytes)",
#ifdef CONFIG_STM32_MEMMAP
/* Now configure the octo Flash in MemoryMapped (access by address) */
ret = stm32_ospi_set_memorymap(dev);
if (ret != 0) {
LOG_ERR("Error (%d): setting NOR in MemoryMapped mode", ret);
return -EINVAL;
}
LOG_DBG("NOR octo-flash in MemoryMapped mode at 0x%lx (0x%x bytes)",
(long)(STM32_OSPI_BASE_ADDRESS),
dev_cfg->flash_size);
#else
LOG_DBG("NOR octo-flash at 0x%lx (0x%x bytes)",
(long)(STM32_OSPI_BASE_ADDRESS),
dev_cfg->flash_size);
#endif /* CONFIG_STM32_MEMMAP */
return 0;
}