1212#include <zephyr/kernel.h>
1313#include <zephyr/toolchain.h>
1414#include <zephyr/arch/common/ffs.h>
15+ #include <zephyr/sys/__assert.h>
1516#include <zephyr/sys/util.h>
1617#include <soc.h>
18+ #include <string.h>
1719#include <zephyr/drivers/pinctrl.h>
1820#include <zephyr/drivers/clock_control/stm32_clock_control.h>
1921#include <zephyr/drivers/clock_control.h>
@@ -385,6 +387,66 @@ static bool qspi_address_is_valid(const struct device *dev, off_t addr,
385387 return (addr >= 0 ) && ((uint64_t )addr + (uint64_t )size <= flash_size );
386388}
387389
390+ #ifdef CONFIG_STM32_MEMMAP
391+ /* Must be called inside qspi_lock_thread(). */
392+ static int stm32_qspi_set_memory_mapped (const struct device * dev )
393+ {
394+ int ret ;
395+ HAL_StatusTypeDef hal_ret ;
396+ struct flash_stm32_qspi_data * dev_data = dev -> data ;
397+
398+ QSPI_CommandTypeDef cmd = {
399+ .Instruction = SPI_NOR_CMD_READ ,
400+ .Address = 0 ,
401+ .InstructionMode = QSPI_INSTRUCTION_1_LINE ,
402+ .AddressMode = QSPI_ADDRESS_1_LINE ,
403+ .DataMode = QSPI_DATA_1_LINE ,
404+ };
405+
406+ qspi_set_address_size (dev , & cmd );
407+ if (IS_ENABLED (STM32_QSPI_USE_QUAD_IO )) {
408+ ret = qspi_prepare_quad_read (dev , & cmd );
409+ if (ret < 0 ) {
410+ return ret ;
411+ }
412+ }
413+
414+ QSPI_MemoryMappedTypeDef mem_mapped = {
415+ .TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE ,
416+ };
417+
418+ hal_ret = HAL_QSPI_MemoryMapped (& dev_data -> hqspi , & cmd , & mem_mapped );
419+ if (hal_ret != 0 ) {
420+ LOG_ERR ("%d: Failed to enable memory mapped" , hal_ret );
421+ return - EIO ;
422+ }
423+
424+ LOG_DBG ("MemoryMap mode enabled" );
425+ return 0 ;
426+ }
427+
428+ static bool stm32_qspi_is_memory_mapped (const struct device * dev )
429+ {
430+ struct flash_stm32_qspi_data * dev_data = dev -> data ;
431+
432+ return READ_BIT (dev_data -> hqspi .Instance -> CCR , QUADSPI_CCR_FMODE ) == QUADSPI_CCR_FMODE ;
433+ }
434+
435+ static int stm32_qspi_abort (const struct device * dev )
436+ {
437+ struct flash_stm32_qspi_data * dev_data = dev -> data ;
438+ HAL_StatusTypeDef hal_ret ;
439+
440+ hal_ret = HAL_QSPI_Abort (& dev_data -> hqspi );
441+ if (hal_ret != HAL_OK ) {
442+ LOG_ERR ("%d: QSPI abort failed" , hal_ret );
443+ return - EIO ;
444+ }
445+
446+ return 0 ;
447+ }
448+ #endif
449+
388450static int flash_stm32_qspi_read (const struct device * dev , off_t addr ,
389451 void * data , size_t size )
390452{
@@ -401,6 +463,27 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
401463 return 0 ;
402464 }
403465
466+ #ifdef CONFIG_STM32_MEMMAP
467+ qspi_lock_thread (dev );
468+
469+ /* Do reads through memory-mapping instead of indirect */
470+ if (!stm32_qspi_is_memory_mapped (dev )) {
471+ ret = stm32_qspi_set_memory_mapped (dev );
472+ if (ret != 0 ) {
473+ LOG_ERR ("READ: failed to set memory mapped" );
474+ goto end ;
475+ }
476+ }
477+
478+ __ASSERT_NO_MSG (stm32_qspi_is_memory_mapped (dev ));
479+
480+ uintptr_t mmap_addr = STM32_QSPI_BASE_ADDRESS + addr ;
481+
482+ LOG_DBG ("Memory-mapped read from 0x%08lx, len %zu" , mmap_addr , size );
483+ memcpy (data , (void * )mmap_addr , size );
484+ ret = 0 ;
485+ goto end ;
486+ #else
404487 QSPI_CommandTypeDef cmd = {
405488 .Instruction = SPI_NOR_CMD_READ ,
406489 .Address = addr ,
@@ -420,7 +503,10 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr,
420503 qspi_lock_thread (dev );
421504
422505 ret = qspi_read_access (dev , & cmd , data , size );
506+ goto end ;
507+ #endif
423508
509+ end :
424510 qspi_unlock_thread (dev );
425511
426512 return ret ;
@@ -482,6 +568,17 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr,
482568
483569 qspi_lock_thread (dev );
484570
571+ #ifdef CONFIG_STM32_MEMMAP
572+ if (stm32_qspi_is_memory_mapped (dev )) {
573+ /* Abort ongoing transfer to force CS high/BUSY deasserted */
574+ ret = stm32_qspi_abort (dev );
575+ if (ret != 0 ) {
576+ LOG_ERR ("Failed to abort memory-mapped access before write" );
577+ goto end ;
578+ }
579+ }
580+ #endif
581+
485582 while (size > 0 ) {
486583 size_t to_write = size ;
487584
@@ -517,7 +614,9 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr,
517614 break ;
518615 }
519616 }
617+ goto end ;
520618
619+ end :
521620 qspi_unlock_thread (dev );
522621
523622 return ret ;
@@ -555,6 +654,17 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr,
555654 qspi_set_address_size (dev , & cmd_erase );
556655 qspi_lock_thread (dev );
557656
657+ #ifdef CONFIG_STM32_MEMMAP
658+ if (stm32_qspi_is_memory_mapped (dev )) {
659+ /* Abort ongoing transfer to force CS high/BUSY deasserted */
660+ ret = stm32_qspi_abort (dev );
661+ if (ret != 0 ) {
662+ LOG_ERR ("Failed to abort memory-mapped access before erase" );
663+ goto end ;
664+ }
665+ }
666+ #endif
667+
558668 while ((size > 0 ) && (ret == 0 )) {
559669 cmd_erase .Address = addr ;
560670 qspi_send_cmd (dev , & cmd_write_en );
@@ -596,7 +706,9 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr,
596706 }
597707 qspi_wait_until_ready (dev );
598708 }
709+ goto end ;
599710
711+ end :
600712 qspi_unlock_thread (dev );
601713
602714 return ret ;
@@ -1367,9 +1479,20 @@ static int flash_stm32_qspi_init(const struct device *dev)
13671479 }
13681480#endif /* CONFIG_FLASH_PAGE_LAYOUT */
13691481
1482+ #ifdef CONFIG_STM32_MEMMAP
1483+ ret = stm32_qspi_set_memory_mapped (dev );
1484+ if (ret != 0 ) {
1485+ LOG_ERR ("Failed to enable memory-mapped mode: %d" , ret );
1486+ return ret ;
1487+ }
1488+ LOG_INF ("Memory-mapped NOR quad-flash at 0x%lx (0x%x bytes)" ,
1489+ (long )(STM32_QSPI_BASE_ADDRESS ),
1490+ dev_cfg -> flash_size );
1491+ #else
13701492 LOG_INF ("NOR quad-flash at 0x%lx (0x%x bytes)" ,
13711493 (long )(STM32_QSPI_BASE_ADDRESS ),
13721494 dev_cfg -> flash_size );
1495+ #endif
13731496
13741497 return 0 ;
13751498}
0 commit comments