This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new 82ab33aed66 arch/arm/src/stm32{h7,f7,l4}: add 4-bit wide bus support
for MMC/eMMC cards
82ab33aed66 is described below
commit 82ab33aed66671598bcff2b768a7f02a55e8c9a3
Author: DuoYuWang <[email protected]>
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 <[email protected]>
---
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 0e713eadb07..f1419f258c8 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 | \
@@ -2045,7 +2049,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);
}
/****************************************************************************
@@ -2089,6 +2110,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