Skip to content

Commit 24a783d

Browse files
drivers: sdmmc: stm32: introduce cache flush & invalidation for DMA
Introduce steps to maintain cache coherence around DMA accesses to the underlying SD / eMMC storage. Signed-off-by: Attie Grande <attie.grande@argentum-systems.co.uk>
1 parent d31c6e9 commit 24a783d

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

drivers/disk/sdmmc_stm32.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <zephyr/pm/policy.h>
1818
#include <zephyr/logging/log.h>
1919
#include <zephyr/irq.h>
20+
#include <zephyr/cache.h>
2021
#include <soc.h>
2122
#include <stm32_ll_rcc.h>
2223

@@ -518,6 +519,12 @@ static int stm32_sdmmc_read_blocks(HandleTypeDef *hsd, uint8_t *data_buf,
518519

519520
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
520521

522+
/* A flush is performed before the DMA operation, to prevent accidental data
523+
* loss when the buffer is not properly aligned to the cache-line (e.g:
524+
* 32-bytes for STM32H7).
525+
*/
526+
sys_cache_data_flush_and_invd_range(data_buf, BLOCKSIZE * num_sector);
527+
521528
#ifdef CONFIG_SDMMC_STM32_EMMC
522529
hal_ret = HAL_MMC_ReadBlocks_DMA(hsd, data_buf, start_sector, num_sector);
523530
#else
@@ -568,6 +575,13 @@ static int stm32_sdmmc_access_read(struct disk_info *disk, uint8_t *data_buf,
568575

569576
k_sem_take(&priv->sync, K_FOREVER);
570577

578+
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
579+
/* Invalidate after the operation is complete, to protect against
580+
* speculative / spurious reads.
581+
*/
582+
sys_cache_data_invd_range(data_buf, BLOCKSIZE * num_sector);
583+
#endif
584+
571585
#if STM32_SDMMC_USE_DMA_SHARED
572586
if (HAL_DMA_DeInit(&priv->dma_txrx_handle) != HAL_OK) {
573587
err = -EIO;
@@ -598,6 +612,8 @@ static int stm32_sdmmc_write_blocks(HandleTypeDef *hsd,
598612

599613
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
600614

615+
sys_cache_data_flush_range(data_buf, BLOCKSIZE * num_sector);
616+
601617
#ifdef CONFIG_SDMMC_STM32_EMMC
602618
hal_ret = HAL_MMC_WriteBlocks_DMA(hsd, data_buf, start_sector, num_sector);
603619
#else

0 commit comments

Comments
 (0)