qspi: stm32: Add code to switch flash memory to use 4 SIO pins
For proper operation of QUADSPI IP block, both sides of communication; NOR flash memory and STM32 controller need to support 4 IO transmission. After this change the QSPI stm32 driver is able to program NOR flash memory to switch itself to use all 4 IO lines (SIO[0123]) to transmit and receive data. The QE bit (in SPI-NOR's Status Register) is the non-volatile one, so setting it is done only once (at first boot of the device). Signed-off-by: Lukasz Majewski <lukma@denx.de>
This commit is contained in:
parent
029f49fc99
commit
c1b60e7fb6
2 changed files with 102 additions and 0 deletions
|
@ -90,6 +90,10 @@ struct flash_stm32_qspi_data {
|
|||
* 24-bit addresses.
|
||||
*/
|
||||
bool flag_access_32bit: 1;
|
||||
/*
|
||||
* If set IO operations will be perfromed on SIO[0123] pins
|
||||
*/
|
||||
bool flag_quad_io_en: 1;
|
||||
};
|
||||
|
||||
#define DEV_NAME(dev) ((dev)->name)
|
||||
|
@ -665,6 +669,101 @@ static int qspi_program_addr_4b(const struct device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int qspi_read_status_register(const struct device *dev, uint8_t *reg)
|
||||
{
|
||||
QSPI_CommandTypeDef cmd = {
|
||||
.Instruction = SPI_NOR_CMD_RDSR,
|
||||
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
||||
.DataMode = QSPI_DATA_1_LINE,
|
||||
};
|
||||
|
||||
return qspi_read_access(dev, &cmd, reg, sizeof(*reg));
|
||||
}
|
||||
|
||||
static int qspi_write_status_register(const struct device *dev, uint8_t reg)
|
||||
{
|
||||
QSPI_CommandTypeDef cmd = {
|
||||
.Instruction = SPI_NOR_CMD_WRSR,
|
||||
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
||||
.DataMode = QSPI_DATA_1_LINE,
|
||||
};
|
||||
|
||||
return qspi_write_access(dev, &cmd, ®, sizeof(reg));
|
||||
}
|
||||
|
||||
static int qspi_write_enable(const struct device *dev)
|
||||
{
|
||||
uint8_t reg;
|
||||
int ret;
|
||||
|
||||
QSPI_CommandTypeDef cmd_write_en = {
|
||||
.Instruction = SPI_NOR_CMD_WREN,
|
||||
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
|
||||
};
|
||||
|
||||
ret = qspi_send_cmd(dev, &cmd_write_en);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
do {
|
||||
ret = qspi_read_status_register(dev, ®);
|
||||
} while (!ret && !(reg & SPI_NOR_WEL_BIT));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qspi_program_quad_io(const struct device *dev)
|
||||
{
|
||||
struct flash_stm32_qspi_data *data = DEV_DATA(dev);
|
||||
uint8_t reg;
|
||||
int ret;
|
||||
|
||||
/* Check if QE bit setting is required */
|
||||
ret = qspi_read_status_register(dev, ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Quit early when QE bit is already set */
|
||||
if (reg & SPI_NOR_QE_BIT) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = qspi_write_enable(dev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
reg |= SPI_NOR_QE_BIT;
|
||||
ret = qspi_write_status_register(dev, reg);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = qspi_wait_until_ready(dev);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = qspi_read_status_register(dev, ®);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if QE bit programming is finished */
|
||||
if (!(reg & SPI_NOR_QE_BIT)) {
|
||||
LOG_ERR("Quad Enable [QE] bit in status reg not set");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
out:
|
||||
LOG_INF("Flash - QUAD mode enabled [SR:0x%02x]", reg);
|
||||
data->flag_quad_io_en = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int spi_nor_process_bfp(const struct device *dev,
|
||||
const struct jesd216_param_header *php,
|
||||
const struct jesd216_bfp *bfp)
|
||||
|
@ -723,6 +822,8 @@ static int spi_nor_process_bfp(const struct device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
qspi_program_quad_io(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
/* Status register bits */
|
||||
#define SPI_NOR_WIP_BIT BIT(0) /* Write in progress */
|
||||
#define SPI_NOR_WEL_BIT BIT(1) /* Write enable latch */
|
||||
#define SPI_NOR_QE_BIT BIT(6) /* Enable quad mode */
|
||||
|
||||
/* Control register bits */
|
||||
#define SPI_NOR_4BYTE_BIT BIT(5) /* 4B addressing */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue