Skip to content

Commit f3f661a

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 f3f661a

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

drivers/disk/sdmmc_stm32.c

Lines changed: 22 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

@@ -561,13 +562,32 @@ static int stm32_sdmmc_access_read(struct disk_info *disk, uint8_t *data_buf,
561562
}
562563
#endif
563564

565+
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
566+
/* A flush is performed before the DMA operation, to prevent accidental data
567+
* loss when the buffer is not properly aligned to the cache-line (e.g:
568+
* 32-bytes for STM32H7).
569+
*/
570+
sys_cache_data_flush_and_invd_range(data_buf, BLOCKSIZE * num_sector);
571+
#endif
572+
564573
err = stm32_sdmmc_read_blocks(&priv->hsd, data_buf, start_sector, num_sector);
565574
if (err != 0) {
566575
goto end;
567576
}
568577

569578
k_sem_take(&priv->sync, K_FOREVER);
570579

580+
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
581+
/* Invalidate again after the operation is complete, to protect against
582+
* speculative / spurious reads. Note that this is slightly unsafe when
583+
* `data_buf` is not aligned to the cache line, and shares the cache line
584+
* with other data... Hopefully the previous (otherwise unnecessary) flush &
585+
* invalidate reduces this risk enough.
586+
* This is a balance between forcing callers to have aligned buffers.
587+
*/
588+
sys_cache_data_invd_range(data_buf, BLOCKSIZE * num_sector);
589+
#endif
590+
571591
#if STM32_SDMMC_USE_DMA_SHARED
572592
if (HAL_DMA_DeInit(&priv->dma_txrx_handle) != HAL_OK) {
573593
err = -EIO;
@@ -598,6 +618,8 @@ static int stm32_sdmmc_write_blocks(HandleTypeDef *hsd,
598618

599619
#if STM32_SDMMC_USE_DMA || IS_ENABLED(DT_PROP(DT_DRV_INST(0), idma))
600620

621+
sys_cache_data_flush_range(data_buf, BLOCKSIZE * num_sector);
622+
601623
#ifdef CONFIG_SDMMC_STM32_EMMC
602624
hal_ret = HAL_MMC_WriteBlocks_DMA(hsd, data_buf, start_sector, num_sector);
603625
#else

0 commit comments

Comments
 (0)