]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mmc: mmci: stm32: manage block gap hardware flow control
authorYann Gautier <yann.gautier@foss.st.com>
Mon, 19 Jun 2023 11:51:18 +0000 (13:51 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Tue, 20 Jun 2023 09:44:40 +0000 (11:44 +0200)
In stm32 sdmmc variant revision v3.0, a block gap hardware flow control
should be used with bus speed modes SDR104 and HS200.
It is enabled by writing a non-null value to the new added register
MMCI_STM32_FIFOTHRR.
The threshold will be 2^(N-1) bytes, so we can use the ffs() function to
compute the value N to be written to the register. The threshold used
should be the data block size, but must not be bigger than the FIFO size.

Signed-off-by: Yann Gautier <yann.gautier@foss.st.com>
Link: https://lore.kernel.org/r/20230619115120.64474-5-yann.gautier@foss.st.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
drivers/mmc/host/mmci.h
drivers/mmc/host/mmci_stm32_sdmmc.c

index b1968cafc58bb51501f4cc6ed67cf88439ec9930..361954249d04dae86b9882177ed357682560d018 100644 (file)
 #define MCI_STM32_BUSYD0ENDMASK        BIT(21)
 
 #define MMCIMASK1              0x040
+
+/* STM32 sdmmc data FIFO threshold register */
+#define MMCI_STM32_FIFOTHRR    0x044
+#define MMCI_STM32_THR_MASK    GENMASK(3, 0)
+
 #define MMCIFIFOCNT            0x048
 #define MMCIFIFO               0x080 /* to 0x0bc */
 
index 1bc775b9e714e7b21fcdcef4e05b36d403c4b629..29634d1dc289b56b747768155979dd9443fd84b4 100644 (file)
@@ -361,6 +361,19 @@ static u32 sdmmc_get_dctrl_cfg(struct mmci_host *host)
 
        datactrl = mmci_dctrl_blksz(host);
 
+       if (host->hw_revision >= 3) {
+               u32 thr = 0;
+
+               if (host->mmc->ios.timing == MMC_TIMING_UHS_SDR104 ||
+                   host->mmc->ios.timing == MMC_TIMING_MMC_HS200) {
+                       thr = ffs(min_t(unsigned int, host->data->blksz,
+                                       host->variant->fifosize));
+                       thr = min_t(u32, thr, MMCI_STM32_THR_MASK);
+               }
+
+               writel_relaxed(thr, host->base + MMCI_STM32_FIFOTHRR);
+       }
+
        if (host->mmc->card && mmc_card_sdio(host->mmc->card) &&
            host->data->blocks == 1)
                datactrl |= MCI_DPSM_STM32_MODE_SDIO;