drivers: flash: stm32: qspi: support 1-4-4 and 1-1-4 quad read modes
Adds support for 1-4-4 and 1-1-4 read modes. SFDP is used to query for available read instructions, then the fastest one is used. Signed-off-by: Georgij Cernysiov <geo.cgv@gmail.com>
This commit is contained in:
parent
0216353263
commit
bbdfe6d9e0
1 changed files with 58 additions and 22 deletions
|
@ -43,6 +43,8 @@ LOG_MODULE_REGISTER(flash_stm32_qspi, CONFIG_FLASH_LOG_LEVEL);
|
||||||
#define STM32_QSPI_FIFO_THRESHOLD 8
|
#define STM32_QSPI_FIFO_THRESHOLD 8
|
||||||
#define STM32_QSPI_CLOCK_PRESCALER_MAX 255
|
#define STM32_QSPI_CLOCK_PRESCALER_MAX 255
|
||||||
|
|
||||||
|
#define STM32_QSPI_UNKNOWN_MODE (0xFF)
|
||||||
|
|
||||||
#define STM32_QSPI_USE_DMA DT_NODE_HAS_PROP(DT_INST_PARENT(0), dmas)
|
#define STM32_QSPI_USE_DMA DT_NODE_HAS_PROP(DT_INST_PARENT(0), dmas)
|
||||||
|
|
||||||
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor)
|
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor)
|
||||||
|
@ -90,6 +92,7 @@ struct flash_stm32_qspi_data {
|
||||||
struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES];
|
struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES];
|
||||||
/* Number of bytes per page */
|
/* Number of bytes per page */
|
||||||
uint16_t page_size;
|
uint16_t page_size;
|
||||||
|
enum jesd216_mode_type mode;
|
||||||
int cmd_status;
|
int cmd_status;
|
||||||
struct stream dma;
|
struct stream dma;
|
||||||
uint8_t qspi_write_cmd;
|
uint8_t qspi_write_cmd;
|
||||||
|
@ -133,17 +136,29 @@ static inline void qspi_set_address_size(const struct device *dev,
|
||||||
cmd->AddressSize = QSPI_ADDRESS_24_BITS;
|
cmd->AddressSize = QSPI_ADDRESS_24_BITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void qspi_prepare_quad_read(const struct device *dev,
|
static inline int qspi_prepare_quad_read(const struct device *dev,
|
||||||
QSPI_CommandTypeDef *cmd)
|
QSPI_CommandTypeDef *cmd)
|
||||||
{
|
{
|
||||||
struct flash_stm32_qspi_data *dev_data = dev->data;
|
struct flash_stm32_qspi_data *dev_data = dev->data;
|
||||||
|
|
||||||
if (IS_ENABLED(STM32_QSPI_USE_QUAD_IO) && dev_data->flag_quad_io_en) {
|
if (IS_ENABLED(STM32_QSPI_USE_QUAD_IO) && dev_data->flag_quad_io_en) {
|
||||||
|
switch (dev_data->mode) {
|
||||||
|
case JESD216_MODE_114:
|
||||||
|
cmd->AddressMode = QSPI_ADDRESS_1_LINE;
|
||||||
|
break;
|
||||||
|
case JESD216_MODE_144:
|
||||||
|
cmd->AddressMode = QSPI_ADDRESS_4_LINES;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
cmd->Instruction = dev_data->qspi_read_cmd;
|
cmd->Instruction = dev_data->qspi_read_cmd;
|
||||||
cmd->AddressMode = QSPI_ADDRESS_4_LINES;
|
|
||||||
cmd->DataMode = QSPI_DATA_4_LINES;
|
cmd->DataMode = QSPI_DATA_4_LINES;
|
||||||
cmd->DummyCycles = dev_data->qspi_read_cmd_latency;
|
cmd->DummyCycles = dev_data->qspi_read_cmd_latency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int qspi_prepare_quad_program(const struct device *dev,
|
static inline int qspi_prepare_quad_program(const struct device *dev,
|
||||||
|
@ -329,7 +344,10 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
|
||||||
};
|
};
|
||||||
|
|
||||||
qspi_set_address_size(dev, &cmd);
|
qspi_set_address_size(dev, &cmd);
|
||||||
qspi_prepare_quad_read(dev, &cmd);
|
ret = qspi_prepare_quad_read(dev, &cmd);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
qspi_lock_thread(dev);
|
qspi_lock_thread(dev);
|
||||||
|
|
||||||
ret = qspi_read_access(dev, &cmd, data, size);
|
ret = qspi_read_access(dev, &cmd, data, size);
|
||||||
|
@ -884,34 +902,52 @@ static int spi_nor_process_bfp(const struct device *dev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only check if the 1-4-4 (i.e. 4READ) fast read operation is
|
* Only check if the 1-4-4 (i.e. 4READ) or 1-1-4 (QREAD)
|
||||||
* supported - other modes - e.g. 1-1-4 (QREAD) or 1-1-2 (DREAD) are
|
* is supported - other modes are not.
|
||||||
* not.
|
|
||||||
*/
|
*/
|
||||||
if (IS_ENABLED(STM32_QSPI_USE_QUAD_IO)) {
|
if (IS_ENABLED(STM32_QSPI_USE_QUAD_IO)) {
|
||||||
|
const enum jesd216_mode_type supported_modes[] = { JESD216_MODE_114,
|
||||||
|
JESD216_MODE_144 };
|
||||||
|
struct jesd216_bfp_dw15 dw15;
|
||||||
struct jesd216_instr res;
|
struct jesd216_instr res;
|
||||||
|
|
||||||
rc = jesd216_bfp_read_support(php, bfp, JESD216_MODE_144, &res);
|
/* reset active mode */
|
||||||
if (rc > 0) {
|
data->mode = STM32_QSPI_UNKNOWN_MODE;
|
||||||
/* Program flash memory to use SIO[0123] */
|
|
||||||
rc = qspi_program_quad_io(dev);
|
|
||||||
if (rc) {
|
|
||||||
LOG_ERR("Unable to enable QUAD IO mode: %d\n",
|
|
||||||
rc);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INF("Mode: 1-4-4 with instr:[0x%x] supported!",
|
/* query supported read modes, begin from the slowest */
|
||||||
res.instr);
|
for (size_t i = 0; i < ARRAY_SIZE(supported_modes); ++i) {
|
||||||
|
rc = jesd216_bfp_read_support(php, bfp, supported_modes[i], &res);
|
||||||
|
if (rc >= 0) {
|
||||||
|
LOG_INF("Quad read mode %d instr [0x%x] supported",
|
||||||
|
supported_modes[i], res.instr);
|
||||||
|
|
||||||
data->qspi_read_cmd = res.instr;
|
data->mode = supported_modes[i];
|
||||||
data->qspi_read_cmd_latency = res.wait_states;
|
data->qspi_read_cmd = res.instr;
|
||||||
if (res.mode_clocks) {
|
data->qspi_read_cmd_latency = res.wait_states;
|
||||||
data->qspi_read_cmd_latency +=
|
|
||||||
res.mode_clocks;
|
if (res.mode_clocks) {
|
||||||
|
data->qspi_read_cmd_latency += res.mode_clocks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* don't continue when there is no supported mode */
|
||||||
|
if (data->mode == STM32_QSPI_UNKNOWN_MODE) {
|
||||||
|
LOG_ERR("No supported flash read mode found");
|
||||||
|
return -ENOTSUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INF("Quad read mode %d instr [0x%x] will be used", data->mode, res.instr);
|
||||||
|
|
||||||
|
/* enable QE */
|
||||||
|
rc = qspi_program_quad_io(dev);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Failed to enable Quad mode: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue