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.
|
* 24-bit addresses.
|
||||||
*/
|
*/
|
||||||
bool flag_access_32bit: 1;
|
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)
|
#define DEV_NAME(dev) ((dev)->name)
|
||||||
|
@ -665,6 +669,101 @@ static int qspi_program_addr_4b(const struct device *dev)
|
||||||
return ret;
|
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,
|
static int spi_nor_process_bfp(const struct device *dev,
|
||||||
const struct jesd216_param_header *php,
|
const struct jesd216_param_header *php,
|
||||||
const struct jesd216_bfp *bfp)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
/* Status register bits */
|
/* Status register bits */
|
||||||
#define SPI_NOR_WIP_BIT BIT(0) /* Write in progress */
|
#define SPI_NOR_WIP_BIT BIT(0) /* Write in progress */
|
||||||
#define SPI_NOR_WEL_BIT BIT(1) /* Write enable latch */
|
#define SPI_NOR_WEL_BIT BIT(1) /* Write enable latch */
|
||||||
|
#define SPI_NOR_QE_BIT BIT(6) /* Enable quad mode */
|
||||||
|
|
||||||
/* Control register bits */
|
/* Control register bits */
|
||||||
#define SPI_NOR_4BYTE_BIT BIT(5) /* 4B addressing */
|
#define SPI_NOR_4BYTE_BIT BIT(5) /* 4B addressing */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue