Skip to content

imx95-a55: add GPIO and eMMC (USDHC) support with partition table parsing, verify use i.mx95-FRDM EVK#18501

Draft
jasonbu wants to merge 7 commits intoapache:masterfrom
jasonbu:imx95_emmc8bit
Draft

imx95-a55: add GPIO and eMMC (USDHC) support with partition table parsing, verify use i.mx95-FRDM EVK#18501
jasonbu wants to merge 7 commits intoapache:masterfrom
jasonbu:imx95_emmc8bit

Conversation

@jasonbu
Copy link
Contributor

@jasonbu jasonbu commented Mar 6, 2026

Summary

Add GPIO and eMMC (USDHC) support for the i.MX95 A55 EVK board, enabling 8-bit eMMC access with MBR/GPT partition table parsing.

Changes

1. imx9: add GPIO support for imx95

  • Add imx95 GPIO register definitions (same IP block as imx93)
  • Fill g_gpio_base[] array for imx95
  • Include imx95_gpio.h from the common header
  • Compile imx9_gpio.c / imx9_gpiobase.c for imx95 in cmake

2. imx95-a55-evk: add USDHC eMMC driver support

  • Create imx95_pinmux.h / imx95_ccm.h / imx95_pll.h hardware definitions for imx95
  • Add USDHC1 8-bit eMMC pin mux and clock macros to board.h
  • Create board-level imx9_usdhc.c glue code
  • Update imx9_bringup.c with DMA allocator and USDHC init
  • Add CONFIG_IMX9_CLK_OVER_SCMI compile-time guards in imx9_usdhc.c to isolate the IMX95 SCMI clock path from the existing IMX93 direct-CCM path — no functional change for IMX93

3. imx9: usdhc fix dmapreflight rejecting small unaligned buffers

  • imx9_dmapreflight() rejected unaligned buffers unconditionally, but dmarecvsetup() has a bounce path via priv->rxbuffer for small transfers
  • Add a buflen > sizeof(priv->rxbuffer) check so that small reads (e.g. ext_csd 512-byte stack buffer) can use the bounce buffer instead of failing with -EFAULT

4. imx95-a55-evk: add MBR/GPT partition table parsing on eMMC

  • Parse the partition table on /dev/mmcsd0 during board bringup and register each partition as /dev/mmcsd0pN
  • Add custom MBR handler for unnamed partition entries

Impact

  • IMX93 code paths are fully preserved behind #ifndef CONFIG_IMX9_CLK_OVER_SCMI guards — zero functional change for existing IMX93 boards
  • The dmapreflight fix is a generic improvement that benefits all imx9 USDHC users
  • If using i.mx95-FRDM EVK, able to mount the /boot partition same with uboot/linux, after patch.
  • mmcsd 8bit not support fixed , as previous we only hardcode 4bit width support.

Testing

Verified on i.MX95 FRDM EVK:

  • eMMC device recognized and initialized (8-bit mode)
  • Partition table parsed, partitions registered
  • mount -t vfat /dev/mmcsd0p0 /data works

need enable feature by menuconfig.
defconfig diff did not bring in these patch chain

diff --git a/boards/arm64/imx9/imx95-a55-evk/configs/nsh/defconfig b/boards/arm64/imx9/imx95-a55-evk/configs/nsh/defconfig
index 7acc9fba627..f6e527a5829 100644
--- a/boards/arm64/imx9/imx95-a55-evk/configs/nsh/defconfig
+++ b/boards/arm64/imx9/imx95-a55-evk/configs/nsh/defconfig
@@ -15,11 +15,16 @@ CONFIG_ARCH_CHIP_IMX9=y
 CONFIG_ARCH_EARLY_PRINT=y
 CONFIG_ARCH_INTERRUPTSTACK=4096
 CONFIG_ARCH_USE_MMU=y
+CONFIG_BASE_DEFCONFIG="imx95-a55-evk/nsh"
 CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARD_LATE_INITIALIZE=y
 CONFIG_BOARD_LOOPSPERMSEC=241712
 CONFIG_BUILTIN=y
 CONFIG_DEBUG_ASSERTIONS=y
+CONFIG_DEBUG_ASSERTIONS_EXPRESSION=y
 CONFIG_DEBUG_FEATURES=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_FS_ERROR=y
 CONFIG_DEBUG_FULLOPT=y
 CONFIG_DEBUG_SYMBOLS=y
 CONFIG_DEFAULT_TASK_STACKSIZE=8192
@@ -30,6 +35,7 @@ CONFIG_FS_FAT=y
 CONFIG_FS_FATTIME=y
 CONFIG_FS_PROCFS=y
 CONFIG_FS_ROMFS=y
+CONFIG_GPT_PARTITION=y
 CONFIG_GRAN=y
 CONFIG_HAVE_CXX=y
 CONFIG_HAVE_CXXINITIALIZE=y
@@ -37,13 +43,21 @@ CONFIG_IDLETHREAD_STACKSIZE=8192
 CONFIG_IMX9_DMA_ALLOC=y
 CONFIG_IMX9_DMA_ALLOC_POOL_SIZE=81920
 CONFIG_IMX9_LPUART1=y
+CONFIG_IMX9_USDHC1=y
+CONFIG_IMX9_USDHC1_INVERT_CD=y
+CONFIG_IMX9_USDHC1_WIDTH_D1_D8=y
 CONFIG_INIT_ENTRYPOINT="nsh_main"
 CONFIG_INTELHEX_BINARY=y
 CONFIG_LPUART1_SERIAL_CONSOLE=y
+CONFIG_MBR_PARTITION=y
+CONFIG_MMCSD=y
+CONFIG_MMCSD_SDIO=y
+CONFIG_NAME_MAX=96
 CONFIG_NDEBUG=y
 CONFIG_NSH_ARCHINIT=y
 CONFIG_NSH_BUILTIN_APPS=y
 CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_PROMPT_MAX=32
 CONFIG_NSH_READLINE=y
 CONFIG_PREALLOC_TIMERS=4
 CONFIG_RAMLOG=y
@@ -56,6 +70,7 @@ CONFIG_SCHED_HPWORK=y
 CONFIG_SCHED_HPWORKPRIORITY=192
 CONFIG_SCHED_LPWORK=y
 CONFIG_SCHED_LPWORKPRIORITY=50
+CONFIG_SDIO_BLOCKSETUP=y
 CONFIG_SPINLOCK=y
 CONFIG_STACK_COLORATION=y
 CONFIG_START_MONTH=3
nsh> mount -t vfat /dev/mmcsd0p0 /data
nsh> ls -l /data/nuttx.bin
 -rw-rw-rw-      515184 /data/nuttx.bin

ostest passed in i.MX95 FRDM EVK

[2026-03-06 17:57:11] user_main: Exiting
[2026-03-06 17:57:11] ostest_main: Exiting with status 0
[2026-03-06 17:57:11] nsh> 

jasonbu added 7 commits March 6, 2026 16:17
arm64_modifyreg8.c, arm64_modifyreg16.c, arm64_modifyreg32.c were
present in Make.defs but missing from CMakeLists.txt, causing link
errors when building with cmake.

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
…upport

The MMC CMD6 bus width switch was gated on priv->buswidth which is
derived from the SD SCR register. For MMC cards this field is never
set (unless SDIO_CAPS_4BIT_ONLY), so the CMD6 was skipped while the
host PROCTL DTW was still changed - causing a bus width mismatch and
data transfer timeouts.

Fix by checking priv->caps instead of priv->buswidth for MMC cards.
Also select EXT_CSD_BUS_WIDTH_8 when host reports SDIO_CAPS_8BIT.

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
Rename IMX9_IRQ_uSDHC{1,2,3} to IMX9_IRQ_USDHC{1,2,3} in both arm
and arm64 imx95_irq.h to follow the all-caps naming convention used
by imx93_irq.h and the rest of the NuttX codebase. Remove the now
unnecessary USDHC IRQ alias block from arm64 imx95_irq.h.

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
Add imx95 GPIO register definitions (same IP block as imx93), fill
g_gpio_base[] array for imx95, include imx95_gpio.h from the common
header, and compile imx9_gpio.c/imx9_gpiobase.c for imx95 in cmake.

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
Port USDHC1 (eMMC) driver to the i.MX95 FRDM EVK board:
- Create imx95_pinmux.h with SD1/USDHC1 pin definitions
- Add USDHC1 pin macros to board.h
- Create board-level imx9_usdhc.c glue code
- Update imx9_bringup.c with DMA allocator and USDHC init
- Add SCMI clock guards in imx9_usdhc.c (imx95 clock roots
  are owned by System Manager, direct CCM writes are no-ops)
- Fix CCM_CR_USDHC2 copy-paste bug to CCM_CR_USDHC1

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
imx9_dmapreflight() rejected unaligned buffers unconditionally, but
dmarecvsetup() has a bounce path via priv->rxbuffer for small
transfers. Add a buflen > sizeof(priv->rxbuffer) check so that
small reads (e.g. ext_csd 512-byte stack buffer) can use the
bounce buffer instead of failing with -EFAULT.

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
Parse the partition table on /dev/mmcsd0 during board bringup and
register each partition as /dev/mmcsd0pN. MBR partitions have no
name field so a custom handler is needed instead of the default
register_partition which skips unnamed entries.

Verify by i.mx95 FRDM
'mount -t vfat /dev/mmcsd0p0 /data'

Signed-off-by: buxiasen <buxiasen@xiaomi.com>
@github-actions github-actions bot added Arch: arm Issues related to ARM (32-bit) architecture Arch: arm64 Issues related to ARM64 (64-bit) architecture Area: Drivers Drivers issues Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces. Board: arm64 labels Mar 6, 2026
@simbit18
Copy link
Contributor

simbit18 commented Mar 6, 2026

Hi @fdcavalcanti @tmedicci @eren-terzioglu We are receiving this error on all PRs. Can you check it?

Error: board/esp32_bringup.c:275:9: error: implicit declaration of function 'btn_lower_initialize'; did you mean 'nullmtd_initialize'? [-Wimplicit-function-declaration]
  275 |   ret = btn_lower_initialize("/dev/buttons");
      |         ^~~~~~~~~~~~~~~~~~~

Boards

  Cleaning...
HEAD detached at pull/18501/merge
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   boards/xtensa/esp32/esp32-devkitc/configs/bmp280/defconfig
	modified:   boards/xtensa/esp32/esp32-devkitc/configs/buttons/defconfig
	modified:   boards/xtensa/esp32/esp32-ethernet-kit/configs/buttons/defconfig
	modified:   boards/xtensa/esp32/esp32-lyrat/configs/buttons/defconfig
	modified:   boards/xtensa/esp32/esp32-wrover-kit/configs/buttons/defconfig
	modified:   boards/xtensa/esp32/esp32-wrover-kit/configs/lua/defconfig
====================================================================================
Configuration/Tool: esp32-ethernet-kit/buttons
2026-03-06 10:13:47
------------------------------------------------------------------------------------
  Cleaning...
  Configuring...
  Building NuttX...
board/esp32_bringup.c: In function 'esp32_bringup':
Error: board/esp32_bringup.c:275:9: error: implicit declaration of function 'btn_lower_initialize'; did you mean 'nullmtd_initialize'? [-Wimplicit-function-declaration]
  275 |   ret = btn_lower_initialize("/dev/buttons");
      |         ^~~~~~~~~~~~~~~~~~~~
      |         nullmtd_initialize
make[1]: *** [/github/workspace/sources/nuttx/boards/Board.mk:83: esp32_bringup.o] Error 1
make[1]: Target 'libboard.a' not remade because of errors.
make: *** [tools/LibTargets.mk:89: arch/xtensa/src/board/libboard.a] Error 2
make: Target 'all' not remade because of errors.
/github/workspace/sources/nuttx/tools/testbuild.sh: line 385: /github/workspace/sources/nuttx/../nuttx/nuttx.manifest: No such file or directory
  [1/1] Normalize esp32-ethernet-kit/buttons
18d17
< CONFIG_ARCH_IRQBUTTONS=y
34d32
< CONFIG_INPUT_BUTTONS_LOWER=y
Saving the new configuration file
HEAD detached at pull/18501/merge
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   boards/xtensa/esp32/esp32-ethernet-kit/configs/buttons/defconfig

no changes added to commit (use "git add" and/or "git commit -a")
====================================================================================

https://github.com/apache/nuttx/actions/runs/22758561387/job/66009383296#logs

@fdcavalcanti
Copy link
Contributor

Hi @fdcavalcanti @tmedicci @eren-terzioglu We are receiving this error on all PRs. Can you check it?

Error: board/esp32_bringup.c:275:9: error: implicit declaration of function 'btn_lower_initialize'; did you mean 'nullmtd_initialize'? [-Wimplicit-function-declaration]
  275 |   ret = btn_lower_initialize("/dev/buttons");
      |         ^~~~~~~~~~~~~~~~~~~

Boards

  Cleaning...
HEAD detached at pull/18501/merge
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   boards/xtensa/esp32/esp32-devkitc/configs/bmp280/defconfig
	modified:   boards/xtensa/esp32/esp32-devkitc/configs/buttons/defconfig
	modified:   boards/xtensa/esp32/esp32-ethernet-kit/configs/buttons/defconfig
	modified:   boards/xtensa/esp32/esp32-lyrat/configs/buttons/defconfig
	modified:   boards/xtensa/esp32/esp32-wrover-kit/configs/buttons/defconfig
	modified:   boards/xtensa/esp32/esp32-wrover-kit/configs/lua/defconfig
====================================================================================
Configuration/Tool: esp32-ethernet-kit/buttons
2026-03-06 10:13:47
------------------------------------------------------------------------------------
  Cleaning...
  Configuring...
  Building NuttX...
board/esp32_bringup.c: In function 'esp32_bringup':
Error: board/esp32_bringup.c:275:9: error: implicit declaration of function 'btn_lower_initialize'; did you mean 'nullmtd_initialize'? [-Wimplicit-function-declaration]
  275 |   ret = btn_lower_initialize("/dev/buttons");
      |         ^~~~~~~~~~~~~~~~~~~~
      |         nullmtd_initialize
make[1]: *** [/github/workspace/sources/nuttx/boards/Board.mk:83: esp32_bringup.o] Error 1
make[1]: Target 'libboard.a' not remade because of errors.
make: *** [tools/LibTargets.mk:89: arch/xtensa/src/board/libboard.a] Error 2
make: Target 'all' not remade because of errors.
/github/workspace/sources/nuttx/tools/testbuild.sh: line 385: /github/workspace/sources/nuttx/../nuttx/nuttx.manifest: No such file or directory
  [1/1] Normalize esp32-ethernet-kit/buttons
18d17
< CONFIG_ARCH_IRQBUTTONS=y
34d32
< CONFIG_INPUT_BUTTONS_LOWER=y
Saving the new configuration file
HEAD detached at pull/18501/merge
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   boards/xtensa/esp32/esp32-ethernet-kit/configs/buttons/defconfig

no changes added to commit (use "git add" and/or "git commit -a")
====================================================================================

https://github.com/apache/nuttx/actions/runs/22758561387/job/66009383296#logs

There's a fix coming very soon.

@cederom
Copy link
Contributor

cederom commented Mar 6, 2026

Very nice @jasonbu thank you.. lets just wait for the CI fix :-)

@mzanders you are user of this hw too can you please take a look? :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Arch: arm Issues related to ARM (32-bit) architecture Arch: arm64 Issues related to ARM64 (64-bit) architecture Area: Drivers Drivers issues Board: arm64 Size: XL The size of the change in this PR is very large. Consider breaking down the PR into smaller pieces.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants