You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by an...@apache.org on 2021/05/07 21:39:22 UTC

[incubator-nuttx] 01/03: stm32f7:SDMMC:Use 250 Ms Data path timeout, regardless of Card Clock frequency

This is an automated email from the ASF dual-hosted git repository.

antmerlino pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit c45e03b75f4f5b099cbc2a455f4b2f2c5ee1b904
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Wed May 5 12:26:29 2021 -0700

    stm32f7:SDMMC:Use 250 Ms Data path timeout, regardless of Card Clock frequency
---
 arch/arm/src/stm32f7/stm32_sdmmc.c | 60 +++++++++++++++++++++++++++++---------
 1 file changed, 46 insertions(+), 14 deletions(-)

diff --git a/arch/arm/src/stm32f7/stm32_sdmmc.c b/arch/arm/src/stm32f7/stm32_sdmmc.c
index 047210e..1ce89cc 100644
--- a/arch/arm/src/stm32f7/stm32_sdmmc.c
+++ b/arch/arm/src/stm32f7/stm32_sdmmc.c
@@ -49,6 +49,7 @@
 #include "stm32_dtcm.h"
 #include "stm32_dma.h"
 #include "stm32_gpio.h"
+#include "stm32_rcc.h"
 #include "stm32_sdmmc.h"
 
 #if defined(CONFIG_STM32F7_SDMMC1) || defined(CONFIG_STM32F7_SDMMC2)
@@ -130,6 +131,11 @@
 #  else
 #    undef CONFIG_STM32F7_SDMMC1_DMAPRIO
 #  endif
+#  if STM32_RCC_DCKCFGR2_SDMMCSRC == RCC_DCKCFGR2_SDMMCSEL_48MHZ
+#      define STM32_SDMMC1_CLK UINT32_C(48000000)
+#  else
+#      define STM32_SDMMC1_CLK STM32_SYSCLK_FREQUENCY
+#  endif
 #endif
 
 #ifdef CONFIG_STM32F7_SDMMC2
@@ -143,6 +149,11 @@
 #  else
 #    undef CONFIG_STM32F7_SDMMC2_DMAPRIO
 #  endif
+#  if STM32_RCC_DCKCFGR2_SDMMCSRC == RCC_DCKCFGR2_SDMMCSEL_48MHZ
+#      define STM32_SDMMC2_CLK UINT32_C(48000000)
+#  else
+#      define STM32_SDMMC2_CLK STM32_SYSCLK_FREQUENCY
+#  endif
 #endif
 
 #undef HAVE_SDMMC_SDIO_MODE
@@ -214,9 +225,9 @@
 #define SDMMC_CMDTIMEOUT         (100000)
 #define SDMMC_LONGTIMEOUT        (0x7fffffff)
 
-/* Big DTIMER setting */
+/* DTIMER setting */
 
-#define SDMMC_DTIMER_DATATIMEOUT (0x003d0900) /* 250 ms @ 16 MHz */
+#define SDMMC_DTIMER_DATATIMEOUT_MS 250
 
 /* DMA channel/stream configuration register settings.  The following
  * must be selected.  The DMA driver will select the remaining fields.
@@ -368,6 +379,7 @@ struct stm32_dev_s
 
   uint32_t          base;
   int               nirq;
+  uint32_t          sdio_clk;
 #ifdef CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE
   uint32_t          d0_gpio;
 #endif
@@ -625,6 +637,7 @@ struct stm32_dev_s g_sdmmcdev1 =
   },
   .base              = STM32_SDMMC1_BASE,
   .nirq              = STM32_IRQ_SDMMC1,
+  .sdio_clk          = STM32_SDMMC1_CLK,
 #ifdef CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE
   .d0_gpio           = SDMMC1_SDIO_PULL(GPIO_SDMMC1_D0),
 #endif
@@ -684,6 +697,7 @@ struct stm32_dev_s g_sdmmcdev2 =
   },
   .base              = STM32_SDMMC2_BASE,
   .nirq              = STM32_IRQ_SDMMC2,
+  .sdio_clk          = STM32_SDMMC2_CLK,
 #ifdef CONFIG_MMCSD_SDIOWAIT_WRCOMPLETE
   .d0_gpio           = SDMMC2_SDIO_PULL(GPIO_SDMMC2_D0),
 #endif
@@ -1223,9 +1237,26 @@ static uint8_t stm32_log2(uint16_t value)
 static void stm32_dataconfig(struct stm32_dev_s *priv, uint32_t timeout,
                              uint32_t dlen, uint32_t dctrl)
 {
-  uint32_t regval = 0;
+  uint32_t clkdiv;
+  uint32_t regval;
+  uint32_t sdio_clk = priv->sdio_clk;
+
+  /* Enable data path using a timeout scaled to the SD_CLOCK (the card
+   * clock).
+   */
 
-  /* Enable data path */
+  regval = sdmmc_getreg32(priv, STM32_SDMMC_CLKCR_OFFSET);
+  clkdiv = (regval & STM32_SDMMC_CLKCR_CLKDIV_MASK) >>
+            STM32_SDMMC_CLKCR_CLKDIV_SHIFT;
+
+  if ((regval & STM32_SDMMC_CLKCR_BYPASS) == 0)
+    {
+      sdio_clk = sdio_clk / (2 + clkdiv);
+    }
+
+  /*  Convert Timeout in Ms to SD_CLK counts */
+
+  timeout  = timeout * (sdio_clk / 1000);
 
   sdmmc_putreg32(priv, timeout, STM32_SDMMC_DTIMER_OFFSET); /* Set DTIMER */
   sdmmc_putreg32(priv, dlen,    STM32_SDMMC_DLEN_OFFSET);   /* Set DLEN */
@@ -1271,8 +1302,11 @@ static void stm32_datadisable(struct stm32_dev_s *priv)
 
   /* Reset DTIMER */
 
-  sdmmc_putreg32(priv, SDMMC_DTIMER_DATATIMEOUT, STM32_SDMMC_DTIMER_OFFSET);
-  sdmmc_putreg32(priv, 0, STM32_SDMMC_DLEN_OFFSET);   /* Reset DLEN */
+  sdmmc_putreg32(priv, UINT32_MAX, STM32_SDMMC_DTIMER_OFFSET);
+
+  /* Reset DLEN */
+
+  sdmmc_putreg32(priv,  0, STM32_SDMMC_DLEN_OFFSET);
 
   /* Reset DCTRL DTEN, DTDIR, DTMODE, DMAEN, and DBLOCKSIZE fields */
 
@@ -2254,8 +2288,8 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
 
   dblksize = stm32_log2(priv->blocksize) <<
              STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
-  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT * ((nbytes + 511) >> 9),
-                   nbytes, dblksize | STM32_SDMMC_DCTRL_DTDIR);
+  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT_MS, nbytes,
+                   dblksize | STM32_SDMMC_DCTRL_DTDIR);
 
   /* And enable interrupts */
 
@@ -2310,8 +2344,7 @@ static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const
 
   dblksize = stm32_log2(priv->blocksize) <<
              STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
-  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT * ((nbytes + 511) >> 9),
-                   nbytes, dblksize);
+  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT_MS, nbytes, dblksize);
 
   /* Enable TX interrupts */
 
@@ -3061,8 +3094,8 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev,
 
   dblksize = stm32_log2(priv->blocksize) <<
              STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
-  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT * ((buflen + 511) >> 9),
-                   buflen, dblksize | STM32_SDMMC_DCTRL_DTDIR);
+  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT_MS, buflen,
+                   dblksize | STM32_SDMMC_DCTRL_DTDIR);
 
   /* Configure the RX DMA */
 
@@ -3165,8 +3198,7 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
 
   dblksize = stm32_log2(priv->blocksize) <<
              STM32_SDMMC_DCTRL_DBLOCKSIZE_SHIFT;
-  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT * ((buflen + 511) >> 9),
-                   buflen, dblksize);
+  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT_MS, buflen, dblksize);
 
   /* Configure the TX DMA */