Browse Source

drivers: flash: Support i.MX FlexSPI NOR driver with XIP

This change allows writing to the flash while running in XIP mode,
and enables mcuboot or NVS settings to be used on i.MX RT socs.

Signed-off-by: Pieter De Gendt <pieter.degendt@basalte.be>
pull/34331/head
Pieter De Gendt 4 years ago committed by Maureen Helm
parent
commit
add98e766a
  1. 4
      drivers/flash/CMakeLists.txt
  2. 34
      drivers/flash/Kconfig.mcux
  3. 71
      drivers/flash/flash_mcux_flexspi_nor.c
  4. 4
      drivers/memc/CMakeLists.txt
  5. 23
      drivers/memc/memc_mcux_flexspi.c
  6. 2
      drivers/memc/memc_mcux_flexspi.h
  7. 4
      soc/arm/nxp_imx/rt/soc.c
  8. 2
      west.yml

4
drivers/flash/CMakeLists.txt

@ -21,6 +21,10 @@ zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c) @@ -21,6 +21,10 @@ zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c)
zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_NOR flash_mcux_flexspi_nor.c)
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_ESP32 flash_esp32.c)
if(CONFIG_FLASH_MCUX_FLEXSPI_XIP)
zephyr_code_relocate(flash_mcux_flexspi_nor.c ${CONFIG_FLASH_MCUX_FLEXSPI_XIP_MEM}_TEXT)
endif()
if(CONFIG_SOC_FLASH_STM32)
if(CONFIG_SOC_SERIES_STM32H7X)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32H7X flash_stm32h7x.c)

34
drivers/flash/Kconfig.mcux

@ -34,4 +34,38 @@ config FLASH_MCUX_FLEXSPI_NOR @@ -34,4 +34,38 @@ config FLASH_MCUX_FLEXSPI_NOR
select MEMC
select MEMC_MCUX_FLEXSPI
config FLASH_MCUX_FLEXSPI_XIP
bool "MCUX FlexSPI flash access with xip"
depends on MEMC_MCUX_FLEXSPI
depends on (CODE_FLEXSPI || CODE_FLEXSPI2)
select XIP
select CODE_DATA_RELOCATION
help
Allows using the flash API while running in XIP.
WARNING: It is possible to overwrite the running application itself.
if FLASH_MCUX_FLEXSPI_XIP
choice FLASH_MCUX_FLEXSPI_XIP_MEM_TARGET
prompt "FlexSPI drivers relocation target"
default FLASH_MCUX_FLEXSPI_XIP_MEM_ITCM
help
Select the location to run the FlexSPI drivers when using
the flash API.
config FLASH_MCUX_FLEXSPI_XIP_MEM_ITCM
bool "ITCM"
config FLASH_MCUX_FLEXSPI_XIP_MEM_SRAM
bool "SRAM"
endchoice
config FLASH_MCUX_FLEXSPI_XIP_MEM
string
default "ITCM" if FLASH_MCUX_FLEXSPI_XIP_MEM_ITCM
default "SRAM" if FLASH_MCUX_FLEXSPI_XIP_MEM_SRAM
endif # FLASH_MCUX_FLEXSPI_XIP
endif # HAS_MCUX_FLEXSPI

71
drivers/flash/flash_mcux_flexspi_nor.c

@ -22,18 +22,21 @@ @@ -22,18 +22,21 @@
LOG_MODULE_REGISTER(flash_flexspi_nor, CONFIG_FLASH_LOG_LEVEL);
enum {
/* SPI instructions */
READ_ID,
READ_STATUS_REG,
WRITE_STATUS_REG,
/* Instructions matching with XIP layout */
READ_FAST_QUAD_OUTPUT,
READ_FAST_OUTPUT,
READ_NORMAL_OUTPUT,
READ_STATUS,
WRITE_ENABLE,
ERASE_SECTOR,
ERASE_CHIP,
/* Quad SPI instructions */
READ_FAST_QUAD_OUTPUT,
PAGE_PROGRAM_INPUT,
PAGE_PROGRAM_QUAD_INPUT,
READ_ID,
WRITE_STATUS_REG,
ENTER_QPI,
EXIT_QPI,
READ_STATUS_REG,
ERASE_CHIP,
};
struct flash_flexspi_nor_config {
@ -86,6 +89,32 @@ static const uint32_t flash_flexspi_nor_lut[][4] = { @@ -86,6 +89,32 @@ static const uint32_t flash_flexspi_nor_lut[][4] = {
kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),
},
[READ_FAST_OUTPUT] = {
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0B,
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08,
kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
},
[READ_NORMAL_OUTPUT] = {
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_READ,
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04,
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
},
[READ_STATUS] = {
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81,
kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
},
[PAGE_PROGRAM_INPUT] = {
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_PP,
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04,
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
},
[PAGE_PROGRAM_QUAD_INPUT] = {
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32,
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
@ -97,6 +126,11 @@ static const uint32_t flash_flexspi_nor_lut[][4] = { @@ -97,6 +126,11 @@ static const uint32_t flash_flexspi_nor_lut[][4] = {
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x35,
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
},
[EXIT_QPI] = {
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_4PAD, 0xF5,
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
},
};
static int flash_flexspi_nor_get_vendor_id(const struct device *dev,
@ -300,11 +334,16 @@ static int flash_flexspi_nor_write(const struct device *dev, off_t offset, @@ -300,11 +334,16 @@ static int flash_flexspi_nor_write(const struct device *dev, off_t offset,
size_t size = len;
uint8_t *src = (uint8_t *) buffer;
int i;
unsigned int key = 0;
uint8_t *dst = memc_flexspi_get_ahb_address(data->controller,
config->port,
offset);
if (memc_flexspi_is_running_xip(data->controller)) {
key = irq_lock();
}
while (len) {
i = MIN(SPI_NOR_PAGE_SIZE, len);
flash_flexspi_nor_write_enable(dev);
@ -315,6 +354,10 @@ static int flash_flexspi_nor_write(const struct device *dev, off_t offset, @@ -315,6 +354,10 @@ static int flash_flexspi_nor_write(const struct device *dev, off_t offset,
len -= i;
}
if (memc_flexspi_is_running_xip(data->controller)) {
irq_unlock(key);
}
#ifdef CONFIG_HAS_MCUX_CACHE
DCACHE_InvalidateByRange((uint32_t) dst, size);
#endif
@ -329,6 +372,7 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset, @@ -329,6 +372,7 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset,
struct flash_flexspi_nor_data *data = dev->data;
int num_sectors = size / SPI_NOR_SECTOR_SIZE;
int i;
unsigned int key = 0;
uint8_t *dst = memc_flexspi_get_ahb_address(data->controller,
config->port,
@ -344,6 +388,10 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset, @@ -344,6 +388,10 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset,
return -EINVAL;
}
if (memc_flexspi_is_running_xip(data->controller)) {
key = irq_lock();
}
if ((offset == 0) && (size == config->config.flashSize * KB(1))) {
flash_flexspi_nor_write_enable(dev);
flash_flexspi_nor_erase_chip(dev);
@ -359,6 +407,10 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset, @@ -359,6 +407,10 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset,
}
}
if (memc_flexspi_is_running_xip(data->controller)) {
irq_unlock(key);
}
#ifdef CONFIG_HAS_MCUX_CACHE
DCACHE_InvalidateByRange((uint32_t) dst, size);
#endif
@ -397,7 +449,8 @@ static int flash_flexspi_nor_init(const struct device *dev) @@ -397,7 +449,8 @@ static int flash_flexspi_nor_init(const struct device *dev)
return -EINVAL;
}
if (memc_flexspi_set_device_config(data->controller, &config->config,
if (!memc_flexspi_is_running_xip(data->controller) &&
memc_flexspi_set_device_config(data->controller, &config->config,
config->port)) {
LOG_ERR("Could not set device configuration");
return -EINVAL;

4
drivers/memc/CMakeLists.txt

@ -6,3 +6,7 @@ zephyr_linker_sources_ifdef(CONFIG_MEMC_STM32_SDRAM SECTIONS memc_stm32_sdram.ld @@ -6,3 +6,7 @@ zephyr_linker_sources_ifdef(CONFIG_MEMC_STM32_SDRAM SECTIONS memc_stm32_sdram.ld
zephyr_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI memc_mcux_flexspi.c)
zephyr_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_HYPERRAM memc_mcux_flexspi_hyperram.c)
if(CONFIG_FLASH_MCUX_FLEXSPI_XIP)
zephyr_code_relocate(memc_mcux_flexspi.c ${CONFIG_FLASH_MCUX_FLEXSPI_XIP_MEM}_TEXT)
endif()

23
drivers/memc/memc_mcux_flexspi.c

@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(memc_flexspi, CONFIG_MEMC_LOG_LEVEL); @@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(memc_flexspi, CONFIG_MEMC_LOG_LEVEL);
struct memc_flexspi_config {
FLEXSPI_Type *base;
uint8_t *ahb_base;
bool xip;
bool ahb_bufferable;
bool ahb_cacheable;
bool ahb_prefetch;
@ -29,6 +30,13 @@ struct memc_flexspi_data { @@ -29,6 +30,13 @@ struct memc_flexspi_data {
size_t size[kFLEXSPI_PortCount];
};
bool memc_flexspi_is_running_xip(const struct device *dev)
{
const struct memc_flexspi_config *config = dev->config;
return config->xip;
}
int memc_flexspi_update_lut(const struct device *dev, uint32_t index,
const uint32_t *cmd, uint32_t count)
{
@ -107,6 +115,12 @@ static int memc_flexspi_init(const struct device *dev) @@ -107,6 +115,12 @@ static int memc_flexspi_init(const struct device *dev)
const struct memc_flexspi_config *config = dev->config;
flexspi_config_t flexspi_config;
/* we should not configure the device we are running on */
if (memc_flexspi_is_running_xip(dev)) {
LOG_DBG("XIP active on %s, skipping init", dev->name);
return 0;
}
FLEXSPI_GetDefaultConfig(&flexspi_config);
flexspi_config.ahbConfig.enableAHBBufferable = config->ahb_bufferable;
@ -122,10 +136,19 @@ static int memc_flexspi_init(const struct device *dev) @@ -122,10 +136,19 @@ static int memc_flexspi_init(const struct device *dev)
return 0;
}
#if defined(CONFIG_XIP) && defined(CONFIG_CODE_FLEXSPI)
#define MEMC_FLEXSPI_CFG_XIP(node_id) DT_SAME_NODE(node_id, DT_NODELABEL(flexspi))
#elif defined(CONFIG_XIP) && defined(CONFIG_CODE_FLEXSPI2)
#define MEMC_FLEXSPI_CFG_XIP(node_id) DT_SAME_NODE(node_id, DT_NODELABEL(flexspi2))
#else
#define MEMC_FLEXSPI_CFG_XIP(node_id) false
#endif
#define MEMC_FLEXSPI(n) \
static const struct memc_flexspi_config \
memc_flexspi_config_##n = { \
.base = (FLEXSPI_Type *) DT_INST_REG_ADDR(n), \
.xip = MEMC_FLEXSPI_CFG_XIP(DT_DRV_INST(n)), \
.ahb_base = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(n, 1), \
.ahb_bufferable = DT_INST_PROP(n, ahb_bufferable), \
.ahb_cacheable = DT_INST_PROP(n, ahb_cacheable), \

2
drivers/memc/memc_mcux_flexspi.h

@ -8,6 +8,8 @@ @@ -8,6 +8,8 @@
#include <sys/types.h>
#include <fsl_flexspi.h>
bool memc_flexspi_is_running_xip(const struct device *dev);
int memc_flexspi_update_lut(const struct device *dev, uint32_t index,
const uint32_t *cmd, uint32_t count);

4
soc/arm/nxp_imx/rt/soc.c

@ -216,7 +216,9 @@ static ALWAYS_INLINE void clock_init(void) @@ -216,7 +216,9 @@ static ALWAYS_INLINE void clock_init(void)
CLOCK_SetMux(kCLOCK_CanMux, 2); /* Set Can clock source. */
#endif
#if defined(CONFIG_MEMC_MCUX_FLEXSPI) && DT_NODE_HAS_STATUS(DT_NODELABEL(flexspi), okay)
#if !(defined(CONFIG_CODE_FLEXSPI) || defined(CONFIG_CODE_FLEXSPI2)) && \
defined(CONFIG_MEMC_MCUX_FLEXSPI) && \
DT_NODE_HAS_STATUS(DT_NODELABEL(flexspi), okay)
CLOCK_DisableClock(kCLOCK_FlexSpi);
CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 24);
CLOCK_SetMux(kCLOCK_FlexspiMux, 3);

2
west.yml

@ -100,7 +100,7 @@ manifest: @@ -100,7 +100,7 @@ manifest:
revision: f49bd1354616fae4093bf36e5eaee43c51a55127
path: tools/net-tools
- name: hal_nxp
revision: 4560b0a0106bbe47eded4d7af775998c4f6d05c0
revision: 27a464e4885f393dc376a53d9fc8d52078848496
path: modules/hal/nxp
- name: open-amp
revision: de1b85a13032a2de1d8b6695ae5f800b613e739d

Loading…
Cancel
Save