Skip to content

Commit 2bec296

Browse files
committed
drivers: flash: stm32 qspi driver set NOR flash in MemoryMapped
Configures the external NOR Flash in MemoryMapped Mode, at the end of the NOR flash-controller initialization. Then reading/writing are performed in MemoryMapped mode with memcopy (and no more with command mode). In this mode: erasing is not supported anymore. The flash size and address are given by the DTS <reg> property. Signed-off-by: Francois Ramu <[email protected]>
1 parent c54eca3 commit 2bec296

File tree

3 files changed

+108
-4
lines changed

3 files changed

+108
-4
lines changed

drivers/flash/flash_stm32_qspi.c

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
#define STM32_QSPI_USE_QUAD_IO 0
3030
#endif
3131

32+
/* Get the base address of the flash from the DTS node */
33+
#define STM32_QSPI_BASE_ADDRESS DT_REG_ADDR(DT_INST(0, st_stm32_qspi_nor))
34+
3235
#define STM32_QSPI_RESET_GPIO DT_INST_NODE_HAS_PROP(0, reset_gpios)
3336
#define STM32_QSPI_RESET_CMD DT_INST_NODE_HAS_PROP(0, reset_cmd)
3437

@@ -382,6 +385,54 @@ static bool qspi_address_is_valid(const struct device *dev, off_t addr,
382385
return (addr >= 0) && ((uint64_t)addr + (uint64_t)size <= flash_size);
383386
}
384387

388+
#ifdef CONFIG_STM32_MEMMAP
389+
/* Function to return true if the quad-NOR flash is in MemoryMapped else false */
390+
static bool qspi_is_memorymap(const struct device *dev)
391+
{
392+
struct flash_stm32_qspi_data *dev_data = dev->data;
393+
394+
return ((READ_BIT(dev_data->hqspi.Instance->CCR,
395+
QUADSPI_CCR_FMODE) == QUADSPI_CCR_FMODE) ?
396+
true : false);
397+
}
398+
399+
400+
/* Function to configure the memmapped mode */
401+
static int qspi_set_memorymap(const struct device *dev)
402+
{
403+
HAL_StatusTypeDef ret;
404+
struct flash_stm32_qspi_data *dev_data = dev->data;
405+
QSPI_CommandTypeDef s_command = {0};
406+
QSPI_MemoryMappedTypeDef s_memmap_cfg;
407+
408+
/* Reading sequence */
409+
s_command.Instruction = SPI_NOR_CMD_4READ; /* 0x6B also supported */
410+
s_command.InstructionMode = QSPI_INSTRUCTION_1_LINE;
411+
s_command.AddressMode = QSPI_ADDRESS_4_LINES;
412+
s_command.AddressSize = QSPI_ADDRESS_32_BITS; /* valid for stm32H7 and stm32L4 */
413+
s_command.DataMode = QSPI_DATA_4_LINES;
414+
#ifdef CONFIG_SOC_SERIES_STM32H7X
415+
s_command.DummyCycles = SPI_NOR_DUMMY_RD_QUAD; /* less than 10 is too short */
416+
#else
417+
s_command.DummyCycles = 4;/* other value than 4 is too short */
418+
#endif /* CONFIG_SOC_SERIES_STM32H7X */
419+
s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
420+
s_command.AlternateBytesSize = QSPI_ALTERNATE_BYTES_8_BITS;
421+
422+
/* Enable the memory-mapping */
423+
s_memmap_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE;
424+
s_memmap_cfg.TimeOutPeriod = 0;
425+
426+
ret = HAL_QSPI_MemoryMapped(&dev_data->hqspi, &s_command, &s_memmap_cfg);
427+
if (ret != HAL_OK) {
428+
LOG_ERR("%d: Failed to set memory map", ret);
429+
return -EIO;
430+
}
431+
432+
return 0;
433+
}
434+
#endif /* CONFIG_STM32_MEMMAP */
435+
385436
static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
386437
void *data, size_t size)
387438
{
@@ -398,6 +449,15 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
398449
return 0;
399450
}
400451

452+
#ifdef CONFIG_STM32_MEMMAP
453+
if (qspi_is_memorymap(dev)) {
454+
LOG_DBG("MemoryMapped Read offset: 0x%lx, len: %zu",
455+
(long)(STM32_QSPI_BASE_ADDRESS + addr), size);
456+
memcpy(data, (uint8_t *)STM32_QSPI_BASE_ADDRESS + addr, size);
457+
458+
return 0;
459+
}
460+
#endif /* CONFIG_STM32_MEMMAP */
401461
QSPI_CommandTypeDef cmd = {
402462
.Instruction = SPI_NOR_CMD_READ,
403463
.Address = addr,
@@ -457,6 +517,16 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr,
457517
return 0;
458518
}
459519

520+
#ifdef CONFIG_STM32_MEMMAP
521+
if (qspi_is_memorymap(dev)) {
522+
LOG_DBG("MemoryMapped Write offset: 0x%lx, len: %zu",
523+
(long)(STM32_QSPI_BASE_ADDRESS + addr), size);
524+
memcpy((uint8_t *)STM32_QSPI_BASE_ADDRESS + addr, data, size);
525+
526+
return 0;
527+
}
528+
#endif /* CONFIG_STM32_MEMMAP */
529+
460530
QSPI_CommandTypeDef cmd_write_en = {
461531
.Instruction = SPI_NOR_CMD_WREN,
462532
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
@@ -538,6 +608,13 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr,
538608
return 0;
539609
}
540610

611+
#ifdef CONFIG_STM32_MEMMAP
612+
if (qspi_is_memorymap(dev)) {
613+
LOG_INF("MemoryMapped : cannot erase");
614+
return 0;
615+
}
616+
#endif /* CONFIG_STM32_MEMMAP */
617+
541618
QSPI_CommandTypeDef cmd_write_en = {
542619
.Instruction = SPI_NOR_CMD_WREN,
543620
.InstructionMode = QSPI_INSTRUCTION_1_LINE,
@@ -910,6 +987,7 @@ static int qspi_write_status_register(const struct device *dev, uint8_t reg_num,
910987
return qspi_write_access(dev, &cmd, regs_p, size);
911988
}
912989

990+
/* Function send a Write Enable and wait it is effective. */
913991
static int qspi_write_enable(const struct device *dev)
914992
{
915993
uint8_t reg;
@@ -1185,6 +1263,17 @@ static int flash_stm32_qspi_init(const struct device *dev)
11851263
return ret;
11861264
}
11871265

1266+
1267+
#ifdef CONFIG_STM32_MEMMAP
1268+
/* If MemoryMapped then configure skip init */
1269+
if (qspi_is_memorymap(dev)) {
1270+
LOG_INF("NOR init'd in MemMapped mode\n");
1271+
/* Force HAL instance in correct state */
1272+
dev_data->hqspi.State = HAL_QSPI_STATE_BUSY_MEM_MAPPED;
1273+
return 0;
1274+
}
1275+
#endif /* CONFIG_STM32_MEMMAP */
1276+
11881277
#if STM32_QSPI_RESET_GPIO
11891278
flash_stm32_qspi_gpio_reset(dev);
11901279
#endif
@@ -1364,6 +1453,19 @@ static int flash_stm32_qspi_init(const struct device *dev)
13641453
}
13651454
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
13661455

1456+
#ifdef CONFIG_STM32_MEMMAP
1457+
ret = qspi_set_memorymap(dev);
1458+
1459+
if (ret != 0) {
1460+
LOG_ERR("Error (%d): setting NOR in MemoryMapped mode", ret);
1461+
return -EINVAL;
1462+
}
1463+
LOG_INF("NOR in MemoryMapped mode at 0x%lx (0x%x bytes)",
1464+
(long)(STM32_QSPI_BASE_ADDRESS),
1465+
dev_cfg->flash_size);
1466+
1467+
#endif /* CONFIG_STM32_MEMMAP */
1468+
13671469
return 0;
13681470
}
13691471

@@ -1420,7 +1522,7 @@ static const struct flash_stm32_qspi_config flash_stm32_qspi_cfg = {
14201522
.bus = DT_CLOCKS_CELL(STM32_QSPI_NODE, bus)
14211523
},
14221524
.irq_config = flash_stm32_qspi_irq_config_func,
1423-
.flash_size = DT_INST_PROP(0, size) / 8U,
1525+
.flash_size = DT_REG_ADDR_BY_IDX(DT_INST(0, st_stm32_qspi_nor), 1),
14241526
.max_frequency = DT_INST_PROP(0, qspi_max_frequency),
14251527
.pcfg = PINCTRL_DT_DEV_CONFIG_GET(STM32_QSPI_NODE),
14261528
#if STM32_QSPI_RESET_GPIO

drivers/flash/spi_nor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@
6060
#define SPI_NOR_CMD_PP_1_1_4_4B 0x34 /* Quad Page program (1-1-4) 4 Byte Address */
6161
#define SPI_NOR_CMD_PP_1_4_4_4B 0x3e /* Quad Page program (1-4-4) 4 Byte Address */
6262

63+
#define SPI_NOR_CMD_RD_VOL_CFG 0x85 /* Read Volatile configuration register */
64+
#define SPI_NOR_CMD_WR_VOL_CFG 0x81 /* Write Volatile configuration register */
65+
6366
/* Flash octal opcodes */
6467
#define SPI_NOR_OCMD_SE 0x21DE /* Octal Sector erase */
6568
#define SPI_NOR_OCMD_CE 0xC738 /* Octal Chip erase */
@@ -94,6 +97,7 @@
9497

9598
/* Flash Dummy Cycles values */
9699
#define SPI_NOR_DUMMY_RD 8U
100+
#define SPI_NOR_DUMMY_RD_QUAD 10U
97101
#define SPI_NOR_DUMMY_RD_OCTAL 6U
98102
#define SPI_NOR_DUMMY_RD_OCTAL_DTR 6U
99103
#define SPI_NOR_DUMMY_REG_OCTAL 4U

dts/bindings/flash_controller/st,stm32-qspi-nor.yaml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,11 @@ on-bus: qspi
2626
properties:
2727
reg:
2828
required: true
29+
description: Flash Memory base address and size in bytes
2930
qspi-max-frequency:
3031
type: int
3132
required: true
3233
description: Maximum clock frequency of device's QSPI interface in Hz
33-
size:
34-
required: true
35-
description: Flash Memory size in bits
3634
reset-gpios:
3735
type: phandle-array
3836
description: RESETn pin

0 commit comments

Comments
 (0)