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>
This commit is contained in:
parent
13cde704e9
commit
add98e766a
8 changed files with 133 additions and 11 deletions
|
@ -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] = {
|
|||
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] = {
|
|||
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,
|
|||
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,
|
|||
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,
|
|||
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,
|
|||
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,
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
|||
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue