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)
