Skip to content

Commit 81f95f1

Browse files
taltenbachdanieldegrasse
authored andcommitted
drivers: flash: stm32_qspi: Fix flash configuration in dual flash mode
When the QSPI is used in dual flash mode, e.g. on the STM32H747I-DISCO board, only the first flash memory was reset and configured in 4-byte addressing mode. This was in particular causing data to be incorrectly read from the second flash memory and only even bytes were valid during a read. The dual flash mode was only enabled after reading the SFDP table since it is desired to read the table of only one flash memory, not both. This commit changes the driver to only disable the dual mode temporarily while reading the SFDP table, ensuring all other commands and in particular configuration commands are sent to both flash memories. Signed-off-by: Thomas Altenbach <altenbach.thomas@gmail.com>
1 parent d5c7cb1 commit 81f95f1

File tree

1 file changed

+33
-18
lines changed

1 file changed

+33
-18
lines changed

drivers/flash/flash_stm32_qspi.c

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -387,13 +387,27 @@ static int qspi_write_unprotect(const struct device *dev)
387387
static int qspi_read_sfdp(const struct device *dev, off_t addr, void *data,
388388
size_t size)
389389
{
390+
int ret = 0;
390391
struct flash_stm32_qspi_data *dev_data = dev->data;
391392
HAL_StatusTypeDef hal_ret;
392393

393394
__ASSERT(data != NULL, "null destination");
394395

395396
LOG_INF("Reading SFDP");
396397

398+
#if DT_PROP(DT_NODELABEL(quadspi), dual_flash) && defined(QUADSPI_CR_DFM)
399+
/*
400+
* In dual flash mode, reading the SFDP table would cause the parameters from both flash
401+
* memories to be read (first byte read would be the first SFDP byte from the first flash,
402+
* second byte read would be the first SFDP byte from the second flash, ...). Both flash
403+
* memories are expected to be identical so to have identical SFDP. Therefore, the dual
404+
* flash mode is disabled during the reading to obtain the SFDP from a single flash memory
405+
* only.
406+
*/
407+
MODIFY_REG(dev_data->hqspi.Instance->CR, QUADSPI_CR_DFM, QSPI_DUALFLASH_DISABLE);
408+
LOG_DBG("Dual flash mode disabled while reading SFDP");
409+
#endif /* dual_flash */
410+
397411
QSPI_CommandTypeDef cmd = {
398412
.Instruction = JESD216_CMD_READ_SFDP,
399413
.Address = addr,
@@ -409,19 +423,27 @@ static int qspi_read_sfdp(const struct device *dev, off_t addr, void *data,
409423
HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
410424
if (hal_ret != HAL_OK) {
411425
LOG_ERR("%d: Failed to send SFDP instruction", hal_ret);
412-
return -EIO;
426+
ret = -EIO;
427+
goto end;
413428
}
414429

415430
hal_ret = HAL_QSPI_Receive(&dev_data->hqspi, (uint8_t *)data,
416431
HAL_QSPI_TIMEOUT_DEFAULT_VALUE);
417432
if (hal_ret != HAL_OK) {
418433
LOG_ERR("%d: Failed to read SFDP", hal_ret);
419-
return -EIO;
434+
ret = -EIO;
435+
goto end;
420436
}
421437

422438
dev_data->cmd_status = 0;
423439

424-
return 0;
440+
end:
441+
#if DT_PROP(DT_NODELABEL(quadspi), dual_flash) && defined(QUADSPI_CR_DFM)
442+
/* Re-enable the dual flash mode */
443+
MODIFY_REG(dev_data->hqspi.Instance->CR, QUADSPI_CR_DFM, QSPI_DUALFLASH_ENABLE);
444+
#endif /* dual_flash */
445+
446+
return ret;
425447
}
426448

427449
static bool qspi_address_is_valid(const struct device *dev, off_t addr,
@@ -1511,16 +1533,19 @@ static int flash_stm32_qspi_init(const struct device *dev)
15111533
/* Give a bit position from 0 to 31 to the HAL init minus 1 for the DCR1 reg */
15121534
dev_data->hqspi.Init.FlashSize = find_lsb_set(dev_cfg->flash_size) - 2;
15131535
#if DT_PROP(DT_NODELABEL(quadspi), dual_flash) && defined(QUADSPI_CR_DFM)
1536+
dev_data->hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
1537+
dev_data->hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_3_CYCLE;
1538+
dev_data->hqspi.Init.DualFlash = QSPI_DUALFLASH_ENABLE;
1539+
15141540
/*
15151541
* When the DTS has <dual-flash>, it means Dual Flash Mode
15161542
* Even in DUAL flash config, the SDFP is read from one single quad-NOR
15171543
* else the magic nb is wrong (0x46465353)
1518-
* That means that the Dual Flash config is set after the SFDP sequence
1544+
* So configure the driver to read from the first flash when dual flash
1545+
* mode is temporarily disabled. Note that if BK2_NCS is not connected,
1546+
* it is not possible to read from the second flash when dual flash mode
1547+
* is disabled.
15191548
*/
1520-
dev_data->hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
1521-
dev_data->hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_3_CYCLE;
1522-
dev_data->hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
1523-
/* Set Dual Flash Mode only on MemoryMapped */
15241549
dev_data->hqspi.Init.FlashID = QSPI_FLASH_ID_1;
15251550
#endif /* dual_flash */
15261551

@@ -1623,16 +1648,6 @@ static int flash_stm32_qspi_init(const struct device *dev)
16231648
LOG_DBG("Write Un-protected");
16241649

16251650
#ifdef CONFIG_STM32_MEMMAP
1626-
#if DT_PROP(DT_NODELABEL(quadspi), dual_flash) && defined(QUADSPI_CR_DFM)
1627-
/*
1628-
* When the DTS has dual_flash, it means Dual Flash Mode for Memory MAPPED
1629-
* Force Dual Flash mode now, after the SFDP sequence which is reading
1630-
* one quad-NOR only
1631-
*/
1632-
MODIFY_REG(dev_data->hqspi.Instance->CR, (QUADSPI_CR_DFM), QSPI_DUALFLASH_ENABLE);
1633-
LOG_DBG("Dual Flash Mode");
1634-
#endif /* dual_flash */
1635-
16361651
ret = stm32_qspi_set_memory_mapped(dev);
16371652
if (ret != 0) {
16381653
LOG_ERR("Failed to enable memory-mapped mode: %d", ret);

0 commit comments

Comments
 (0)