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)
zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_NOR flash_mcux_flexspi_nor.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) 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_FLASH_STM32)
if(CONFIG_SOC_SERIES_STM32H7X) if(CONFIG_SOC_SERIES_STM32H7X)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32H7X flash_stm32h7x.c) zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32H7X flash_stm32h7x.c)

34
drivers/flash/Kconfig.mcux

@ -34,4 +34,38 @@ config FLASH_MCUX_FLEXSPI_NOR
select MEMC select MEMC
select MEMC_MCUX_FLEXSPI 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 endif # HAS_MCUX_FLEXSPI

71
drivers/flash/flash_mcux_flexspi_nor.c

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

4
drivers/memc/CMakeLists.txt

@ -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 memc_mcux_flexspi.c)
zephyr_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_HYPERRAM memc_mcux_flexspi_hyperram.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);
struct memc_flexspi_config { struct memc_flexspi_config {
FLEXSPI_Type *base; FLEXSPI_Type *base;
uint8_t *ahb_base; uint8_t *ahb_base;
bool xip;
bool ahb_bufferable; bool ahb_bufferable;
bool ahb_cacheable; bool ahb_cacheable;
bool ahb_prefetch; bool ahb_prefetch;
@ -29,6 +30,13 @@ struct memc_flexspi_data {
size_t size[kFLEXSPI_PortCount]; 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, int memc_flexspi_update_lut(const struct device *dev, uint32_t index,
const uint32_t *cmd, uint32_t count) const uint32_t *cmd, uint32_t count)
{ {
@ -107,6 +115,12 @@ static int memc_flexspi_init(const struct device *dev)
const struct memc_flexspi_config *config = dev->config; const struct memc_flexspi_config *config = dev->config;
flexspi_config_t flexspi_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_GetDefaultConfig(&flexspi_config);
flexspi_config.ahbConfig.enableAHBBufferable = config->ahb_bufferable; flexspi_config.ahbConfig.enableAHBBufferable = config->ahb_bufferable;
@ -122,10 +136,19 @@ static int memc_flexspi_init(const struct device *dev)
return 0; 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) \ #define MEMC_FLEXSPI(n) \
static const struct memc_flexspi_config \ static const struct memc_flexspi_config \
memc_flexspi_config_##n = { \ memc_flexspi_config_##n = { \
.base = (FLEXSPI_Type *) DT_INST_REG_ADDR(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_base = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(n, 1), \
.ahb_bufferable = DT_INST_PROP(n, ahb_bufferable), \ .ahb_bufferable = DT_INST_PROP(n, ahb_bufferable), \
.ahb_cacheable = DT_INST_PROP(n, ahb_cacheable), \ .ahb_cacheable = DT_INST_PROP(n, ahb_cacheable), \

2
drivers/memc/memc_mcux_flexspi.h

@ -8,6 +8,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <fsl_flexspi.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, int memc_flexspi_update_lut(const struct device *dev, uint32_t index,
const uint32_t *cmd, uint32_t count); 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)
CLOCK_SetMux(kCLOCK_CanMux, 2); /* Set Can clock source. */ CLOCK_SetMux(kCLOCK_CanMux, 2); /* Set Can clock source. */
#endif #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_DisableClock(kCLOCK_FlexSpi);
CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 24); CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 24);
CLOCK_SetMux(kCLOCK_FlexspiMux, 3); CLOCK_SetMux(kCLOCK_FlexspiMux, 3);

2
west.yml

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

Loading…
Cancel
Save