Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for flash controller with XIP on i.MX RT series #33701

Merged
merged 5 commits into from
Apr 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions drivers/flash/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
43 changes: 43 additions & 0 deletions drivers/flash/Kconfig.mcux
Original file line number Diff line number Diff line change
Expand Up @@ -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"
pdgendt marked this conversation as resolved.
Show resolved Hide resolved
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

pdgendt marked this conversation as resolved.
Show resolved Hide resolved
endif # FLASH_MCUX_FLEXSPI_XIP

endif # HAS_MCUX_FLEXSPI
83 changes: 74 additions & 9 deletions drivers/flash/flash_mcux_flexspi_nor.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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),
Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions drivers/memc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 23 additions & 0 deletions drivers/memc/memc_mcux_flexspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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;
pdgendt marked this conversation as resolved.
Show resolved Hide resolved
}

FLEXSPI_GetDefaultConfig(&flexspi_config);

flexspi_config.ahbConfig.enableAHBBufferable = config->ahb_bufferable;
Expand All @@ -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), \
Expand Down
2 changes: 2 additions & 0 deletions drivers/memc/memc_mcux_flexspi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 2 additions & 0 deletions dts/arm/nxp/nxp_rt1064.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
spi-max-frequency = <133000000>;
status = "okay";
jedec-id = [ef 40 16];
erase-block-size = <4096>;
write-block-size = <1>;
};
};
2 changes: 1 addition & 1 deletion dts/bindings/mtd/nxp,imx-flexspi-nor.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
1 change: 1 addition & 0 deletions soc/arm/nxp_imx/rt/Kconfig.defconfig.series
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions soc/arm/nxp_imx/rt/Kconfig.soc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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

Expand Down
4 changes: 3 additions & 1 deletion soc/arm/nxp_imx/rt/soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion west.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down