Skip to content

Commit add98e7

Browse files
pdgendtMaureenHelm
authored andcommitted
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 <[email protected]>
1 parent 13cde70 commit add98e7

File tree

8 files changed

+133
-11
lines changed

8 files changed

+133
-11
lines changed

drivers/flash/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c)
2121
zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_NOR flash_mcux_flexspi_nor.c)
2222
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_ESP32 flash_esp32.c)
2323

24+
if(CONFIG_FLASH_MCUX_FLEXSPI_XIP)
25+
zephyr_code_relocate(flash_mcux_flexspi_nor.c ${CONFIG_FLASH_MCUX_FLEXSPI_XIP_MEM}_TEXT)
26+
endif()
27+
2428
if(CONFIG_SOC_FLASH_STM32)
2529
if(CONFIG_SOC_SERIES_STM32H7X)
2630
zephyr_sources_ifdef(CONFIG_SOC_SERIES_STM32H7X flash_stm32h7x.c)

drivers/flash/Kconfig.mcux

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,38 @@ config FLASH_MCUX_FLEXSPI_NOR
3434
select MEMC
3535
select MEMC_MCUX_FLEXSPI
3636

37+
config FLASH_MCUX_FLEXSPI_XIP
38+
bool "MCUX FlexSPI flash access with xip"
39+
depends on MEMC_MCUX_FLEXSPI
40+
depends on (CODE_FLEXSPI || CODE_FLEXSPI2)
41+
select XIP
42+
select CODE_DATA_RELOCATION
43+
help
44+
Allows using the flash API while running in XIP.
45+
WARNING: It is possible to overwrite the running application itself.
46+
47+
if FLASH_MCUX_FLEXSPI_XIP
48+
49+
choice FLASH_MCUX_FLEXSPI_XIP_MEM_TARGET
50+
prompt "FlexSPI drivers relocation target"
51+
default FLASH_MCUX_FLEXSPI_XIP_MEM_ITCM
52+
help
53+
Select the location to run the FlexSPI drivers when using
54+
the flash API.
55+
56+
config FLASH_MCUX_FLEXSPI_XIP_MEM_ITCM
57+
bool "ITCM"
58+
59+
config FLASH_MCUX_FLEXSPI_XIP_MEM_SRAM
60+
bool "SRAM"
61+
62+
endchoice
63+
64+
config FLASH_MCUX_FLEXSPI_XIP_MEM
65+
string
66+
default "ITCM" if FLASH_MCUX_FLEXSPI_XIP_MEM_ITCM
67+
default "SRAM" if FLASH_MCUX_FLEXSPI_XIP_MEM_SRAM
68+
69+
endif # FLASH_MCUX_FLEXSPI_XIP
70+
3771
endif # HAS_MCUX_FLEXSPI

drivers/flash/flash_mcux_flexspi_nor.c

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,21 @@
2222
LOG_MODULE_REGISTER(flash_flexspi_nor, CONFIG_FLASH_LOG_LEVEL);
2323

2424
enum {
25-
/* SPI instructions */
26-
READ_ID,
27-
READ_STATUS_REG,
28-
WRITE_STATUS_REG,
25+
/* Instructions matching with XIP layout */
26+
READ_FAST_QUAD_OUTPUT,
27+
READ_FAST_OUTPUT,
28+
READ_NORMAL_OUTPUT,
29+
READ_STATUS,
2930
WRITE_ENABLE,
3031
ERASE_SECTOR,
31-
ERASE_CHIP,
32-
33-
/* Quad SPI instructions */
34-
READ_FAST_QUAD_OUTPUT,
32+
PAGE_PROGRAM_INPUT,
3533
PAGE_PROGRAM_QUAD_INPUT,
34+
READ_ID,
35+
WRITE_STATUS_REG,
3636
ENTER_QPI,
37+
EXIT_QPI,
38+
READ_STATUS_REG,
39+
ERASE_CHIP,
3740
};
3841

3942
struct flash_flexspi_nor_config {
@@ -86,6 +89,32 @@ static const uint32_t flash_flexspi_nor_lut[][4] = {
8689
kFLEXSPI_Command_READ_SDR, kFLEXSPI_4PAD, 0x04),
8790
},
8891

92+
[READ_FAST_OUTPUT] = {
93+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x0B,
94+
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
95+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x08,
96+
kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
97+
},
98+
99+
[READ_NORMAL_OUTPUT] = {
100+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_READ,
101+
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
102+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04,
103+
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
104+
},
105+
106+
[READ_STATUS] = {
107+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x81,
108+
kFLEXSPI_Command_READ_SDR, kFLEXSPI_1PAD, 0x04),
109+
},
110+
111+
[PAGE_PROGRAM_INPUT] = {
112+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_PP,
113+
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
114+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04,
115+
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
116+
},
117+
89118
[PAGE_PROGRAM_QUAD_INPUT] = {
90119
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x32,
91120
kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
@@ -97,6 +126,11 @@ static const uint32_t flash_flexspi_nor_lut[][4] = {
97126
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x35,
98127
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
99128
},
129+
130+
[EXIT_QPI] = {
131+
FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_4PAD, 0xF5,
132+
kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0),
133+
},
100134
};
101135

102136
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,
300334
size_t size = len;
301335
uint8_t *src = (uint8_t *) buffer;
302336
int i;
337+
unsigned int key = 0;
303338

304339
uint8_t *dst = memc_flexspi_get_ahb_address(data->controller,
305340
config->port,
306341
offset);
307342

343+
if (memc_flexspi_is_running_xip(data->controller)) {
344+
key = irq_lock();
345+
}
346+
308347
while (len) {
309348
i = MIN(SPI_NOR_PAGE_SIZE, len);
310349
flash_flexspi_nor_write_enable(dev);
@@ -315,6 +354,10 @@ static int flash_flexspi_nor_write(const struct device *dev, off_t offset,
315354
len -= i;
316355
}
317356

357+
if (memc_flexspi_is_running_xip(data->controller)) {
358+
irq_unlock(key);
359+
}
360+
318361
#ifdef CONFIG_HAS_MCUX_CACHE
319362
DCACHE_InvalidateByRange((uint32_t) dst, size);
320363
#endif
@@ -329,6 +372,7 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset,
329372
struct flash_flexspi_nor_data *data = dev->data;
330373
int num_sectors = size / SPI_NOR_SECTOR_SIZE;
331374
int i;
375+
unsigned int key = 0;
332376

333377
uint8_t *dst = memc_flexspi_get_ahb_address(data->controller,
334378
config->port,
@@ -344,6 +388,10 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset,
344388
return -EINVAL;
345389
}
346390

391+
if (memc_flexspi_is_running_xip(data->controller)) {
392+
key = irq_lock();
393+
}
394+
347395
if ((offset == 0) && (size == config->config.flashSize * KB(1))) {
348396
flash_flexspi_nor_write_enable(dev);
349397
flash_flexspi_nor_erase_chip(dev);
@@ -359,6 +407,10 @@ static int flash_flexspi_nor_erase(const struct device *dev, off_t offset,
359407
}
360408
}
361409

410+
if (memc_flexspi_is_running_xip(data->controller)) {
411+
irq_unlock(key);
412+
}
413+
362414
#ifdef CONFIG_HAS_MCUX_CACHE
363415
DCACHE_InvalidateByRange((uint32_t) dst, size);
364416
#endif
@@ -397,7 +449,8 @@ static int flash_flexspi_nor_init(const struct device *dev)
397449
return -EINVAL;
398450
}
399451

400-
if (memc_flexspi_set_device_config(data->controller, &config->config,
452+
if (!memc_flexspi_is_running_xip(data->controller) &&
453+
memc_flexspi_set_device_config(data->controller, &config->config,
401454
config->port)) {
402455
LOG_ERR("Could not set device configuration");
403456
return -EINVAL;

drivers/memc/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@ zephyr_linker_sources_ifdef(CONFIG_MEMC_STM32_SDRAM SECTIONS memc_stm32_sdram.ld
66

77
zephyr_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI memc_mcux_flexspi.c)
88
zephyr_sources_ifdef(CONFIG_MEMC_MCUX_FLEXSPI_HYPERRAM memc_mcux_flexspi_hyperram.c)
9+
10+
if(CONFIG_FLASH_MCUX_FLEXSPI_XIP)
11+
zephyr_code_relocate(memc_mcux_flexspi.c ${CONFIG_FLASH_MCUX_FLEXSPI_XIP_MEM}_TEXT)
12+
endif()

drivers/memc/memc_mcux_flexspi.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ LOG_MODULE_REGISTER(memc_flexspi, CONFIG_MEMC_LOG_LEVEL);
1616
struct memc_flexspi_config {
1717
FLEXSPI_Type *base;
1818
uint8_t *ahb_base;
19+
bool xip;
1920
bool ahb_bufferable;
2021
bool ahb_cacheable;
2122
bool ahb_prefetch;
@@ -29,6 +30,13 @@ struct memc_flexspi_data {
2930
size_t size[kFLEXSPI_PortCount];
3031
};
3132

33+
bool memc_flexspi_is_running_xip(const struct device *dev)
34+
{
35+
const struct memc_flexspi_config *config = dev->config;
36+
37+
return config->xip;
38+
}
39+
3240
int memc_flexspi_update_lut(const struct device *dev, uint32_t index,
3341
const uint32_t *cmd, uint32_t count)
3442
{
@@ -107,6 +115,12 @@ static int memc_flexspi_init(const struct device *dev)
107115
const struct memc_flexspi_config *config = dev->config;
108116
flexspi_config_t flexspi_config;
109117

118+
/* we should not configure the device we are running on */
119+
if (memc_flexspi_is_running_xip(dev)) {
120+
LOG_DBG("XIP active on %s, skipping init", dev->name);
121+
return 0;
122+
}
123+
110124
FLEXSPI_GetDefaultConfig(&flexspi_config);
111125

112126
flexspi_config.ahbConfig.enableAHBBufferable = config->ahb_bufferable;
@@ -122,10 +136,19 @@ static int memc_flexspi_init(const struct device *dev)
122136
return 0;
123137
}
124138

139+
#if defined(CONFIG_XIP) && defined(CONFIG_CODE_FLEXSPI)
140+
#define MEMC_FLEXSPI_CFG_XIP(node_id) DT_SAME_NODE(node_id, DT_NODELABEL(flexspi))
141+
#elif defined(CONFIG_XIP) && defined(CONFIG_CODE_FLEXSPI2)
142+
#define MEMC_FLEXSPI_CFG_XIP(node_id) DT_SAME_NODE(node_id, DT_NODELABEL(flexspi2))
143+
#else
144+
#define MEMC_FLEXSPI_CFG_XIP(node_id) false
145+
#endif
146+
125147
#define MEMC_FLEXSPI(n) \
126148
static const struct memc_flexspi_config \
127149
memc_flexspi_config_##n = { \
128150
.base = (FLEXSPI_Type *) DT_INST_REG_ADDR(n), \
151+
.xip = MEMC_FLEXSPI_CFG_XIP(DT_DRV_INST(n)), \
129152
.ahb_base = (uint8_t *) DT_INST_REG_ADDR_BY_IDX(n, 1), \
130153
.ahb_bufferable = DT_INST_PROP(n, ahb_bufferable), \
131154
.ahb_cacheable = DT_INST_PROP(n, ahb_cacheable), \

drivers/memc/memc_mcux_flexspi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include <sys/types.h>
99
#include <fsl_flexspi.h>
1010

11+
bool memc_flexspi_is_running_xip(const struct device *dev);
12+
1113
int memc_flexspi_update_lut(const struct device *dev, uint32_t index,
1214
const uint32_t *cmd, uint32_t count);
1315

soc/arm/nxp_imx/rt/soc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,9 @@ static ALWAYS_INLINE void clock_init(void)
216216
CLOCK_SetMux(kCLOCK_CanMux, 2); /* Set Can clock source. */
217217
#endif
218218

219-
#if defined(CONFIG_MEMC_MCUX_FLEXSPI) && DT_NODE_HAS_STATUS(DT_NODELABEL(flexspi), okay)
219+
#if !(defined(CONFIG_CODE_FLEXSPI) || defined(CONFIG_CODE_FLEXSPI2)) && \
220+
defined(CONFIG_MEMC_MCUX_FLEXSPI) && \
221+
DT_NODE_HAS_STATUS(DT_NODELABEL(flexspi), okay)
220222
CLOCK_DisableClock(kCLOCK_FlexSpi);
221223
CLOCK_InitUsb1Pfd(kCLOCK_Pfd0, 24);
222224
CLOCK_SetMux(kCLOCK_FlexspiMux, 3);

west.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ manifest:
100100
revision: f49bd1354616fae4093bf36e5eaee43c51a55127
101101
path: tools/net-tools
102102
- name: hal_nxp
103-
revision: 4560b0a0106bbe47eded4d7af775998c4f6d05c0
103+
revision: 27a464e4885f393dc376a53d9fc8d52078848496
104104
path: modules/hal/nxp
105105
- name: open-amp
106106
revision: de1b85a13032a2de1d8b6695ae5f800b613e739d

0 commit comments

Comments
 (0)