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:23 UTC

[incubator-nuttx] 02/03: stm32h7: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 3e49d49cd950699d2b6358b11f51b5d633cfc0a8
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Thu May 6 09:17:57 2021 -0700

    stm32h7:SDMMC:Use 250 Ms Data path timeout, regardless of Card Clock frequency
---
 arch/arm/src/stm32h7/stm32_sdmmc.c | 65 +++++++++++++++++++++++++++++---------
 1 file changed, 50 insertions(+), 15 deletions(-)

diff --git a/arch/arm/src/stm32h7/stm32_sdmmc.c b/arch/arm/src/stm32h7/stm32_sdmmc.c
index 37a021b..c813eb8 100644
--- a/arch/arm/src/stm32h7/stm32_sdmmc.c
+++ b/arch/arm/src/stm32h7/stm32_sdmmc.c
@@ -167,7 +167,21 @@
 
 #define FIFO_SIZE_IN_BYTES        64
 
-/* Friendly CLKCR bit re-definitions ****************************************/
+/* Friendly Clock source & CLKCR bit re-definitions *************************/
+
+/* If not set in board use default pll1_q_ck clock is selected as
+ * kernel peripheral clock (default after reset)
+ */
+
+#if !defined(STM32_RCC_D1CCIPR_SDMMCSEL)
+#  define STM32_RCC_D1CCIPR_SDMMCSEL  RCC_D1CCIPR_SDMMC_PLL1
+#endif
+
+#if STM32_RCC_D1CCIPR_SDMMCSEL  == RCC_D1CCIPR_SDMMC_PLL1
+#  define STM32_SDMMC_CLK  STM32_PLL1Q_FREQUENCY
+#else
+#  define STM32_SDMMC_CLK  STM32_PLL2R_FREQUENCY
+#endif
 
 #define STM32_CLKCR_RISINGEDGE    (0)
 #define STM32_CLKCR_FALLINGEDGE   STM32_SDMMC_CLKCR_NEGEDGE
@@ -208,9 +222,9 @@
 #define SDMMC_CMDTIMEOUT         (100000)
 #define SDMMC_LONGTIMEOUT        (0x7fffffff)
 
-/* Big DTIMER setting */
+/* DTIMER setting */
 
-#define SDMMC_DTIMER_DATATIMEOUT (6250000) /* 250 ms @ 25 MHz */
+#define SDMMC_DTIMER_DATATIMEOUT_MS  250
 
 /* Block size for multi-block transfers */
 
@@ -1080,7 +1094,10 @@ static uint8_t stm32_log2(uint16_t value)
 static void stm32_dataconfig(struct stm32_dev_s *priv, uint32_t timeout,
                              uint32_t dlen, bool receive)
 {
-  uint32_t dctrl = 0;
+  uint32_t clkdiv;
+  uint32_t regval;
+  uint32_t dctrl;
+  uint32_t sdio_clk = STM32_SDMMC_CLK;
 
   DEBUGASSERT((sdmmc_getreg32(priv, STM32_SDMMC_IDMACTRLR_OFFSET) &
                STM32_SDMMC_IDMACTRLR_IDMAEN) == 0);
@@ -1140,7 +1157,26 @@ static void stm32_dataconfig(struct stm32_dev_s *priv, uint32_t timeout,
 
   /* Enable data path */
 
-  /* Set DTIMER */
+  /* Set DTIMER
+   *
+   * Enable data path using a timeout scaled to the SD_CLOCK (the card
+   * clock).
+   */
+
+  regval = sdmmc_getreg32(priv, STM32_SDMMC_CLKCR_OFFSET);
+  clkdiv = (regval & STM32_SDMMC_CLKCR_CLKDIV_MASK) >>
+            STM32_SDMMC_CLKCR_CLKDIV_SHIFT;
+
+  /* CLKDIV_ of 0x000: is Bypass */
+
+  if (clkdiv != 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);
 
@@ -1174,8 +1210,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, and DBLOCKSIZE fields */
 
@@ -2305,8 +2344,7 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
 
   /* Then set up the SDIO data path */
 
-  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT * ((nbytes + 511) >> 9),
-                   nbytes, true);
+  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT_MS, nbytes, true);
 
   /* Workaround the FIFO data available issue */
 
@@ -2380,8 +2418,7 @@ static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const
 
   /* Then set up the SDIO data path */
 
-  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT * ((nbytes + 511) >> 9),
-                   nbytes, false);
+  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT_MS, nbytes, false);
 
   /* Enable TX interrupts */
 
@@ -3163,8 +3200,7 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev,
 
   /* Then set up the SDIO data path */
 
-  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT * ((buflen + 511) >> 9),
-                   buflen, true);
+  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT_MS, buflen, true);
 
   /* Configure the RX DMA */
 
@@ -3255,8 +3291,7 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
 
   /* Then set up the SDIO data path */
 
-  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT * ((buflen + 511) >> 9),
-                   buflen, false);
+  stm32_dataconfig(priv, SDMMC_DTIMER_DATATIMEOUT_MS, buflen, false);
 
   /* Configure the TX DMA */