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

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

commit 4f90fe351b1d6e14dc0d4a48b0f08ecee7220e79
Author: Matteo Golin <[email protected]>
AuthorDate: Mon Jul 13 17:29:00 2026 -0400

    bcm2711/sdio: Moderate improvement to multi-block transfers
    
    I document the issues encountered with multi-block transfers, namely the
    block count failing to be set correctly. Even though I did test with
    that issue corrected, it required modifications to the upper-half MMCSD
    driver which I am not prepared to test. It also did not fix the time-out
    on multi-block transfers, likely because the method of verifying FIFOs
    have space to write is finicky. For now, limiting the block count of
    transfers resolves the bug!
    
    Signed-off-by: Matteo Golin <[email protected]>
---
 arch/arm64/src/bcm2711/bcm2711_sdio.c          | 20 ++++++++++++++++++--
 arch/arm64/src/bcm2711/hardware/bcm2711_sdio.h |  5 ++++-
 2 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/src/bcm2711/bcm2711_sdio.c 
b/arch/arm64/src/bcm2711/bcm2711_sdio.c
index 093d7c065c1..ef7aed5451f 100644
--- a/arch/arm64/src/bcm2711/bcm2711_sdio.c
+++ b/arch/arm64/src/bcm2711/bcm2711_sdio.c
@@ -65,6 +65,10 @@
 
 #define BWAIT_TIMEOUT_US (50000)
 
+#if CONFIG_MMCSD_MULTIBLOCK_LIMIT > 1
+#warning "This driver experiences issues with multi-block transfers"
+#endif
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -1196,12 +1200,16 @@ static int bcm2711_sendcmd(FAR struct sdio_dev_s *dev, 
uint32_t cmd,
       cmdtm_val |= (BCM_SDIO_CMDTM_CMD_ISDATA | BCM_SDIO_CMDTM_TM_DAT_DIR);
     }
 
-  /* Set multi-block transfer flag */
+  /* Set multi-block transfer flag. Also, we automatically send CMD12 at the
+   * end of the transfer in order to stop it. The upper-half driver does not
+   * do this.
+   */
 
   if (cmd & MMCSD_MULTIBLOCK)
     {
       cmdtm_val |=
           (BCM_SDIO_CMDTM_TM_MULTI_BLOCK | BCM_SDIO_CMDTM_TM_BLKCNT_EN);
+      cmdtm_val |= BCM_SDIO_CMDTM_TM_AUTO_CMD_EN_CMD12;
     }
 
   /* Set index of command */
@@ -1241,6 +1249,14 @@ static void bcm2711_blocksetup(FAR struct sdio_dev_s 
*dev,
   DEBUGASSERT(nblocks <= 0xffff); /* Maximum transfer count */
   DEBUGASSERT(blocklen <= 1023);  /* Maximum block size (limited by FIFO) */
 
+  /* WARNING: if we attempt to set the block count while either DAT/CMD
+   * inhibit statuses are high in the STATUS register, it will fail. I've
+   * determined this happens during multi-block transfers because the MMCSD
+   * upper-half driver configures the block size _after_ sending CMD25. If I
+   * reverse the order, block count is set properly. For now, my strategy is
+   * to limit transfers to 1 block.
+   */
+
   regval |= (blocklen & BCM_SDIO_BLKSIZECNT_BLKSIZE_MASK);
   regval |= ((nblocks & BCM_SDIO_BLKSIZECNT_BLKCNT_MASK)
              << BCM_SDIO_BLKSIZECNT_BLKCNT_SHIFTLEN);
@@ -2124,7 +2140,7 @@ struct sdio_dev_s *bcm2711_sdio_initialize(int slotno)
    * 0x80000008 response code, not sure why that happens though.
    */
 
-  err = bcm2711_mbox_getclkrate(priv->clkid, &priv->baseclk, false);
+  err = bcm2711_mbox_getclkrate(priv->clkid, &priv->baseclk, true);
   if (err != -EAGAIN && err != 0)
     {
       mcerr("Couldn't determine base clock rate for EMMC%d: %d\n",
diff --git a/arch/arm64/src/bcm2711/hardware/bcm2711_sdio.h 
b/arch/arm64/src/bcm2711/hardware/bcm2711_sdio.h
index 802918e40f9..fc1baaafec0 100644
--- a/arch/arm64/src/bcm2711/hardware/bcm2711_sdio.h
+++ b/arch/arm64/src/bcm2711/hardware/bcm2711_sdio.h
@@ -105,7 +105,10 @@
 #define BCM_SDIO_BLKSIZECNT_BLKCNT_MASK (0xffff)
 
 #define BCM_SDIO_CMDTM_TM_BLKCNT_EN (1 << 1)
-#define BCM_SDIO_CMDTM_TM_AUTO_CMD_EN (0x3 << 2)
+#define BCM_SDIO_CMDTM_TM_AUTO_CMD_EN_MASK (0x3 << 2)
+#define BCM_SDIO_CMDTM_TM_AUTO_CMD_EN_NONE (0x0 << 2)
+#define BCM_SDIO_CMDTM_TM_AUTO_CMD_EN_CMD12 (0x1 << 2)
+#define BCM_SDIO_CMDTM_TM_AUTO_CMD_EN_CMD23 (0x2 << 2)
 #define BCM_SDIO_CMDTM_TM_DAT_DIR (1 << 4)
 #define BCM_SDIO_CMDTM_TM_MULTI_BLOCK (1 << 5)
 

Reply via email to