You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2026/08/05 07:55:24 UTC
(nuttx) 04/04: arch/arm/src/stm32{h7,f7,l4}: add 4-bit wide bus support for MMC/eMMC cards
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch releases/13.0
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 3f6db0758cec854b3b126fd529d4ee424a88049c
Author: DuoYuWang <th...@gmail.com>
AuthorDate: Tue Jul 21 07:29:52 2026 +0800
arch/arm/src/stm32{h7,f7,l4}: add 4-bit wide bus support for MMC/eMMC cards
The STM32H7, STM32F7, STM32L4 and common STM32 SDIO/SDMMC drivers failed
to program the WIDBUS bits when switching MMC/eMMC cards to 4-bit mode,
and the MMC transfer clock presets were hardwired to 1-bit bus width.
Add CLOCK_MMC_TRANSFER_4BIT to the common SDIO clock enum, add 4-bit
MMC clock presets, and update stm32_widebus() to use modifyreg32/
sdmmc_modifyreg32 to set the host controller bus width.
Signed-off-by: DuoYuWang <th...@gmail.com>
---
arch/arm/src/common/stm32/stm32_sdio_m3m4_v1.c | 12 ++++++++++++
arch/arm/src/stm32f7/stm32_sdmmc.c | 15 ++++++++++++++
arch/arm/src/stm32h7/stm32_sdmmc.c | 27 ++++++++++++++++++++++++++
arch/arm/src/stm32l4/stm32l4_sdmmc.c | 15 ++++++++++++++
include/nuttx/sdio.h | 5 +++--
5 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/arch/arm/src/common/stm32/stm32_sdio_m3m4_v1.c b/arch/arm/src/common/stm32/stm32_sdio_m3m4_v1.c
index 460ce937c48..47b7b7a02c1 100644
--- a/arch/arm/src/common/stm32/stm32_sdio_m3m4_v1.c
+++ b/arch/arm/src/common/stm32/stm32_sdio_m3m4_v1.c
@@ -165,6 +165,8 @@
SDIO_CLKCR_WIDBUS_D1)
#define SDIO_CLKCR_MMCXFR (SDIO_MMCXFR_CLKDIV | SDIO_CLKCR_EDGE | \
SDIO_CLKCR_WIDBUS_D1)
+#define SDIO_CLKCR_MMCXFR4 (SDIO_MMCXFR_CLKDIV | SDIO_CLKCR_EDGE | \
+ SDIO_CLKCR_WIDBUS_D4)
#define SDIO_CLCKR_SDXFR (SDIO_SDXFR_CLKDIV | SDIO_CLKCR_EDGE | \
SDIO_CLKCR_WIDBUS_D1)
#define SDIO_CLCKR_SDWIDEXFR (SDIO_SDXFR_CLKDIV | SDIO_CLKCR_EDGE | \
@@ -1734,7 +1736,11 @@ static sdio_statset_t stm32_status(struct sdio_dev_s *dev)
static void stm32_widebus(struct sdio_dev_s *dev, bool wide)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint32_t widbus = wide ? SDIO_CLKCR_WIDBUS_D4 : SDIO_CLKCR_WIDBUS_D1;
+
priv->widebus = wide;
+
+ modifyreg32(STM32_SDIO_CLKCR, SDIO_CLKCR_WIDBUS_MASK, widbus);
}
/****************************************************************************
@@ -1777,6 +1783,12 @@ static void stm32_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
clckr = (SDIO_CLKCR_MMCXFR | SDIO_CLKCR_CLKEN);
break;
+ /* Enable in MMC wide (4-bit) operation clocking */
+
+ case CLOCK_MMC_TRANSFER_4BIT:
+ clckr = (SDIO_CLKCR_MMCXFR4 | SDIO_CLKCR_CLKEN);
+ break;
+
/* SD normal operation clocking (wide 4-bit mode) */
case CLOCK_SD_TRANSFER_4BIT:
diff --git a/arch/arm/src/stm32f7/stm32_sdmmc.c b/arch/arm/src/stm32f7/stm32_sdmmc.c
index 772e62572bf..debd8c2b704 100644
--- a/arch/arm/src/stm32f7/stm32_sdmmc.c
+++ b/arch/arm/src/stm32f7/stm32_sdmmc.c
@@ -204,6 +204,9 @@
#define STM32_SDMMC_CLKCR_MMCXFR (STM32_SDMMC_MMCXFR_CLKDIV | \
STM32_SDMMC_CLKCR_EDGE | \
STM32_SDMMC_CLKCR_WIDBUS_D1)
+#define STM32_SDMMC_CLKCR_MMCXFR4 (STM32_SDMMC_MMCXFR_CLKDIV | \
+ STM32_SDMMC_CLKCR_EDGE | \
+ STM32_SDMMC_CLKCR_WIDBUS_D4)
#ifdef STM32_SDMMC_SDXFR_BYPCLKDIV
# define STM32_SDMMC_CLCKR_SDXFR (STM32_SDMMC_CLKCR_BYPASS | \
@@ -1991,7 +1994,13 @@ static sdio_statset_t stm32_status(struct sdio_dev_s *dev)
static void stm32_widebus(struct sdio_dev_s *dev, bool wide)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint32_t widbus = wide ? STM32_SDMMC_CLKCR_WIDBUS_D4 :
+ STM32_SDMMC_CLKCR_WIDBUS_D1;
+
priv->widebus = wide;
+
+ sdmmc_modifyreg32(priv, STM32_SDMMC_CLKCR_OFFSET,
+ STM32_SDMMC_CLKCR_WIDBUS_MASK, widbus);
}
/****************************************************************************
@@ -2035,6 +2044,12 @@ static void stm32_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
clckr = (STM32_SDMMC_CLKCR_MMCXFR | STM32_SDMMC_CLKCR_CLKEN);
break;
+ /* Enable in MMC wide (4-bit) operation clocking */
+
+ case CLOCK_MMC_TRANSFER_4BIT:
+ clckr = (STM32_SDMMC_CLKCR_MMCXFR4 | STM32_SDMMC_CLKCR_CLKEN);
+ break;
+
/* SD normal operation clocking (wide 4-bit mode) */
case CLOCK_SD_TRANSFER_4BIT:
diff --git a/arch/arm/src/stm32h7/stm32_sdmmc.c b/arch/arm/src/stm32h7/stm32_sdmmc.c
index 2176d2719b1..0383dbfa8d9 100644
--- a/arch/arm/src/stm32h7/stm32_sdmmc.c
+++ b/arch/arm/src/stm32h7/stm32_sdmmc.c
@@ -210,6 +210,10 @@
STM32_SDMMC_CLKCR_EDGE | \
STM32_SDMMC_CLKCR_PWRSAV | \
STM32_SDMMC_CLKCR_WIDBUS_D1)
+#define STM32_SDMMC_CLKCR_MMCXFR4 (STM32_SDMMC_MMCXFR_CLKDIV | \
+ STM32_SDMMC_CLKCR_EDGE | \
+ STM32_SDMMC_CLKCR_PWRSAV | \
+ STM32_SDMMC_CLKCR_WIDBUS_D4)
#define STM32_SDMMC_CLCKR_SDXFR (STM32_SDMMC_SDXFR_CLKDIV | \
STM32_SDMMC_CLKCR_EDGE | \
STM32_SDMMC_CLKCR_PWRSAV | \
@@ -2060,7 +2064,24 @@ static sdio_statset_t stm32_status(struct sdio_dev_s *dev)
static void stm32_widebus(struct sdio_dev_s *dev, bool wide)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint32_t regval;
+
priv->widebus = wide;
+
+ regval = sdmmc_getreg32(priv, STM32_SDMMC_CLKCR_OFFSET);
+ regval &= ~STM32_SDMMC_CLKCR_WIDBUS_MASK;
+
+ if (wide)
+ {
+ regval |= STM32_SDMMC_CLKCR_WIDBUS_D4;
+ regval &= ~STM32_SDMMC_CLKCR_PWRSAV;
+ }
+ else
+ {
+ regval |= STM32_SDMMC_CLKCR_WIDBUS_D1;
+ }
+
+ sdmmc_putreg32(priv, regval, STM32_SDMMC_CLKCR_OFFSET);
}
/****************************************************************************
@@ -2104,6 +2125,12 @@ static void stm32_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
clckr = STM32_SDMMC_CLKCR_MMCXFR;
break;
+ /* Enable in MMC wide (4-bit) operation clocking */
+
+ case CLOCK_MMC_TRANSFER_4BIT:
+ clckr = STM32_SDMMC_CLKCR_MMCXFR4;
+ break;
+
/* SD normal operation clocking (wide 4-bit mode) */
case CLOCK_SD_TRANSFER_4BIT:
diff --git a/arch/arm/src/stm32l4/stm32l4_sdmmc.c b/arch/arm/src/stm32l4/stm32l4_sdmmc.c
index 3f1aaef30c8..e0eb3e327b8 100644
--- a/arch/arm/src/stm32l4/stm32l4_sdmmc.c
+++ b/arch/arm/src/stm32l4/stm32l4_sdmmc.c
@@ -155,6 +155,9 @@
#define STM32_SDMMC_CLKCR_MMCXFR (STM32_SDMMC_MMCXFR_CLKDIV | \
STM32_SDMMC_CLKCR_EDGE | \
STM32_SDMMC_CLKCR_WIDBUS_D1)
+#define STM32_SDMMC_CLKCR_MMCXFR4 (STM32_SDMMC_MMCXFR_CLKDIV | \
+ STM32_SDMMC_CLKCR_EDGE | \
+ STM32_SDMMC_CLKCR_WIDBUS_D4)
#define STM32_SDMMC_CLCKR_SDXFR (STM32_SDMMC_SDXFR_CLKDIV | \
STM32_SDMMC_CLKCR_EDGE | \
STM32_SDMMC_CLKCR_WIDBUS_D1)
@@ -1786,7 +1789,13 @@ static sdio_statset_t stm32_status(struct sdio_dev_s *dev)
static void stm32_widebus(struct sdio_dev_s *dev, bool wide)
{
struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ uint32_t widbus = wide ? STM32_SDMMC_CLKCR_WIDBUS_D4 :
+ STM32_SDMMC_CLKCR_WIDBUS_D1;
+
priv->widebus = wide;
+
+ sdmmc_modifyreg32(priv, STM32_SDMMC_CLKCR_OFFSET,
+ STM32_SDMMC_CLKCR_WIDBUS_MASK, widbus);
}
/****************************************************************************
@@ -1830,6 +1839,12 @@ static void stm32_clock(struct sdio_dev_s *dev, enum sdio_clock_e rate)
clckr = (STM32_SDMMC_CLKCR_MMCXFR | STM32_SDMMC_CLKCR_CLKEN);
break;
+ /* Enable in MMC wide (4-bit) operation clocking */
+
+ case CLOCK_MMC_TRANSFER_4BIT:
+ clckr = (STM32_SDMMC_CLKCR_MMCXFR4 | STM32_SDMMC_CLKCR_CLKEN);
+ break;
+
/* SD normal operation clocking (wide 4-bit mode) */
case CLOCK_SD_TRANSFER_4BIT:
diff --git a/include/nuttx/sdio.h b/include/nuttx/sdio.h
index 48b5ff66e52..2a8904f2f75 100644
--- a/include/nuttx/sdio.h
+++ b/include/nuttx/sdio.h
@@ -942,9 +942,10 @@ enum sdio_clock_e
{
CLOCK_SDIO_DISABLED = 0, /* Clock is disabled */
CLOCK_IDMODE, /* Initial ID mode clocking (<400KHz) */
- CLOCK_MMC_TRANSFER, /* MMC normal operation clocking */
+ CLOCK_MMC_TRANSFER, /* MMC normal operation clocking (narrow 1-bit mode) */
CLOCK_SD_TRANSFER_1BIT, /* SD normal operation clocking (narrow 1-bit mode) */
- CLOCK_SD_TRANSFER_4BIT /* SD normal operation clocking (wide 4-bit mode) */
+ CLOCK_SD_TRANSFER_4BIT, /* SD normal operation clocking (wide 4-bit mode) */
+ CLOCK_MMC_TRANSFER_4BIT /* MMC normal operation clocking (wide 4-bit mode) */
};
/* Event set. A uint8_t is big enough to hold a set of 8-events. If more