diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index 2062c10f56fe11..44681b4d77105e 100644 --- a/drivers/flash/CMakeLists.txt +++ b/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_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) diff --git a/drivers/flash/Kconfig.mcux b/drivers/flash/Kconfig.mcux index af52ad06990532..acdab49904b6bc 100644 --- a/drivers/flash/Kconfig.mcux +++ b/drivers/flash/Kconfig.mcux @@ -34,4 +34,47 @@ config FLASH_MCUX_FLEXSPI_NOR select MEMC select MEMC_MCUX_FLEXSPI +config FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER + bool "MCUX FlexSPI NOR write RAM buffer" + default y + depends on FLASH_MCUX_FLEXSPI_NOR + help + Copy the data to a RAM buffer before writing it to the flash. + This prevents faults when the data to write would be located on the + flash itself. + +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 diff --git a/drivers/flash/flash_mcux_flexspi_nor.c b/drivers/flash/flash_mcux_flexspi_nor.c index 0f89e523c38e88..c4ae1060e6c1e8 100644 --- a/drivers/flash/flash_mcux_flexspi_nor.c +++ b/drivers/flash/flash_mcux_flexspi_nor.c @@ -19,21 +19,28 @@ #define NOR_WRITE_SIZE 1 #define NOR_ERASE_VALUE 0xff +#ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER +static uint8_t nor_write_buf[SPI_NOR_PAGE_SIZE]; +#endif + 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 +93,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 +130,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,21 +338,38 @@ 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); +#ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER + memcpy(nor_write_buf, src, i); +#endif flash_flexspi_nor_write_enable(dev); +#ifdef CONFIG_FLASH_MCUX_FLEXSPI_NOR_WRITE_BUFFER + flash_flexspi_nor_page_program(dev, offset, nor_write_buf, i); +#else flash_flexspi_nor_page_program(dev, offset, src, i); +#endif flash_flexspi_nor_wait_bus_busy(dev); memc_flexspi_reset(data->controller); + src += i; offset += i; 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 +384,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 +400,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 +419,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 +461,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; diff --git a/drivers/memc/CMakeLists.txt b/drivers/memc/CMakeLists.txt index c8a30e7071ddc4..8fa6a9fc38571d 100644 --- a/drivers/memc/CMakeLists.txt +++ b/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_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() diff --git a/drivers/memc/memc_mcux_flexspi.c b/drivers/memc/memc_mcux_flexspi.c index e396fae8a8ed1a..4c88235f674de7 100644 --- a/drivers/memc/memc_mcux_flexspi.c +++ b/drivers/memc/memc_mcux_flexspi.c @@ -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 { 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) 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) 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), \ diff --git a/drivers/memc/memc_mcux_flexspi.h b/drivers/memc/memc_mcux_flexspi.h index 6e11db8a4a7bab..1b86b8a78c57b9 100644 --- a/drivers/memc/memc_mcux_flexspi.h +++ b/drivers/memc/memc_mcux_flexspi.h @@ -8,6 +8,8 @@ #include #include +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); diff --git a/dts/arm/nxp/nxp_rt1064.dtsi b/dts/arm/nxp/nxp_rt1064.dtsi index 8acb26befb4c9e..4f1f9f0bb270ee 100644 --- a/dts/arm/nxp/nxp_rt1064.dtsi +++ b/dts/arm/nxp/nxp_rt1064.dtsi @@ -17,5 +17,7 @@ spi-max-frequency = <133000000>; status = "okay"; jedec-id = [ef 40 16]; + erase-block-size = <4096>; + write-block-size = <1>; }; }; diff --git a/dts/bindings/mtd/nxp,imx-flexspi-nor.yaml b/dts/bindings/mtd/nxp,imx-flexspi-nor.yaml index 6991c892e492ed..8bde7df0af6e19 100644 --- a/dts/bindings/mtd/nxp,imx-flexspi-nor.yaml +++ b/dts/bindings/mtd/nxp,imx-flexspi-nor.yaml @@ -5,4 +5,4 @@ description: NXP FlexSPI NOR compatible: "nxp,imx-flexspi-nor" -include: nxp,imx-flexspi-device.yaml +include: ["nxp,imx-flexspi-device.yaml", soc-nv-flash.yaml] diff --git a/soc/arm/nxp_imx/rt/Kconfig.defconfig.series b/soc/arm/nxp_imx/rt/Kconfig.defconfig.series index a413f37b821862..44addb316e8e93 100644 --- a/soc/arm/nxp_imx/rt/Kconfig.defconfig.series +++ b/soc/arm/nxp_imx/rt/Kconfig.defconfig.series @@ -9,6 +9,7 @@ config SOC_SERIES default "rt" config ROM_START_OFFSET + default 0x400 if BOOTLOADER_MCUBOOT default 0x2000 if BOOT_FLEXSPI_NOR || BOOT_SEMC_NOR config CAN_MCUX_FLEXCAN diff --git a/soc/arm/nxp_imx/rt/Kconfig.soc b/soc/arm/nxp_imx/rt/Kconfig.soc index 12495a5bcd14eb..de254ff545db44 100644 --- a/soc/arm/nxp_imx/rt/Kconfig.soc +++ b/soc/arm/nxp_imx/rt/Kconfig.soc @@ -385,6 +385,7 @@ config IPG_DIV menuconfig NXP_IMX_RT_BOOT_HEADER bool "Enable the boot header" + depends on !BOOTLOADER_MCUBOOT help Enable data structures required by the boot ROM to boot the application from an external flash device. @@ -448,11 +449,11 @@ config CODE_ITCM config CODE_FLEXSPI bool "Link code into external FlexSPI-controlled memory" - select NXP_IMX_RT_BOOT_HEADER + select NXP_IMX_RT_BOOT_HEADER if !BOOTLOADER_MCUBOOT config CODE_FLEXSPI2 bool "Link code into internal FlexSPI-controlled memory" - select NXP_IMX_RT_BOOT_HEADER + select NXP_IMX_RT_BOOT_HEADER if !BOOTLOADER_MCUBOOT endchoice diff --git a/soc/arm/nxp_imx/rt/soc.c b/soc/arm/nxp_imx/rt/soc.c index 2b79bec1730328..d818c7a8fd772c 100644 --- a/soc/arm/nxp_imx/rt/soc.c +++ b/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. */ #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); diff --git a/west.yml b/west.yml index 9791a579f33004..ffab6c18b12e0d 100644 --- a/west.yml +++ b/west.yml @@ -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