agent: read-only eMMC support via DesignWare MMC controller (hi3516cv500-family)#105
Merged
Conversation
…500-family)
Wires up just enough of the Synopsys DesignWare MMC host controller at
EMMC_BASE=0x10100000 for the agent to identify an eMMC card and stream
blocks back to the host through CMD_READ — closing the loop on
"defib agent ... :emmc" on the hi3516av300 eMMC board.
Tested on hi3516av300:emmc + D9D16 14.5 GiB: agent reports
CID MID=0x88 / OEM=0x0103 (matches the vendor U-Boot boot log),
FLASH_TYPE_EMMC, and CMD_READ against the FLASH_MEM virtual window
(addr=0x14000000+LBA byte offset) returns real eMMC contents — the
first 24 KiB matches the shipped hi3516av300-emmc-spl.bin blob exactly.
Throughput ~10 KB/s on the 1-bit / slow-divider MVP config, which is
fine for partition dumps.
What's in this PR:
* `agent/emmc_himci.{c,h}` (~470 LOC) — minimal DWMMC driver: pinmux
setup, CRG configuration, controller reset, CMD0/1/2/3/9/7
identification, CMD17 single-block read with FIFO drain. The bootrom's
PERISTAT-driven init returns -1 when PERISTAT[9:8]==0 (where the chip
lands after UART fastboot + truncated vendor SPL), so we bypass that
path entirely and just hardcode mode-1 pinmux values pulled from the
bootrom ROM table at offset 0x7d98.
* `agent/main.c` — eMMC init runs after SPI flash probe fails; on success
it populates `flash_info` with `FLASH_TYPE_EMMC`, CID-derived
jedec_id, capacity, and 512-byte sector size. `handle_read` adds an
eMMC branch that loops block-by-block through `emmc_read_block`. The
`FLASH_MEM + flash_info.size` arithmetic moved to uint64_t — eMMC
capacity values near 4 GiB were overflowing uint32_t and silently
routing reads to the (non-existent) SPI flash window.
* `agent/main.c addr_readable` — extended whitelist for EMMC_BASE,
IO_CTRL0_BASE, and the bootrom mask ROM (BOOTROM_BASE..+64 KiB),
each gated by per-SoC Makefile defines. The bootrom-ROM range is the
source of the pinmux table; eMMC + IO ranges are needed by the driver.
* `agent/spi_flash.h` — adds `FLASH_TYPE_EMMC = 2` to the enum.
* `agent/Makefile` — adds EMMC_BASE / IO_CTRL0_BASE / SYSCTRL_BASE /
BOOTROM_BASE / BOOTROM_SIZE under the hi3516cv500 stanza and threads
the corresponding `-D` defines into CFLAGS. `emmc_himci.c` joins
`SRCS_C` only when EMMC_BASE is set.
Known limitations (clearly intentional MVP cuts):
* 1-bit bus mode (skip CMD6 SWITCH). Setting CTYPE=1 without first
switching the card to 4-bit wedges the data path silently — a real
4-bit path needs CMD6.
* HC capacity capped at uint32_t max - sector (0xFFFFFE00). True
capacity for ≥ 2 GiB eMMC lives in EXT_CSD SEC_COUNT which needs
CMD8 SEND_EXT_CSD (data-bearing command) to retrieve.
* CMD17 single-block only (no CMD18 multi-block / no CMD12 STOP).
* No CMD16 SET_BLOCKLEN (default 512 is fine for the MVP).
* No writes, no erase.
C-side tests (host build) still pass — `make -C agent test` runs 5412
assertions. The Python suite still passes — 527 / 2 skipped. The Lint
& Type Check job stays green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The cv500-family eMMC av300 board (
hi3516av300:emmc) gets defib's boot protocol working as of #103, but the agent itself has no idea what eMMC is —flash_initprobes SPI NOR via FMC, finds nothing, and falls back to no-flash. CMD_READ against the FLASH_MEM virtual window has nowhere to route.This PR teaches the agent to drive the Synopsys DesignWare MMC host controller (EMMC_BASE=0x10100000), bring up an eMMC card, and stream blocks back through the existing CMD_READ. End-to-end verified on the real board: bytes returned through
defib agent read --chip hi3516av300:emmc -p /dev/ttyUSB2 --address 0x14000000 --size 0x6000match the shippedhi3516av300-emmc-spl.binexactly (≈10 KB/s).What
```
agent/Makefile | 16 +-
agent/emmc_himci.c | 485 +++++++++++++++++++++++++++++++++++++++++++++++++++++
agent/emmc_himci.h | 36 ++++
agent/main.c | 78 ++++++++-
agent/spi_flash.h | 1 +
```
`agent/emmc_himci.{c,h}` — minimal DWMMC driver (~470 LOC): pinmux setup, CRG configuration, controller reset, CMD0/1/2/3/9/7 identification, CMD17 single-block read with FIFO drain. The bootrom's PERISTAT-driven init returns -1 when `PERISTAT[9:8]==0` (the state the chip lands in after UART fastboot + truncated vendor SPL), so we bypass that path entirely and hardcode mode-1 pinmux values pulled from the bootrom ROM at offset 0x7d98.
`agent/main.c` — eMMC init runs after SPI flash probe fails. On success it populates `flash_info` with `FLASH_TYPE_EMMC=2`, CID-derived jedec_id, capacity, and 512-byte sector size. `handle_read` adds an eMMC branch that loops block-by-block through `emmc_read_block`. The `FLASH_MEM + flash_info.size` arithmetic moved to `uint64_t` — eMMC capacity values near 4 GiB were overflowing `uint32_t` and silently routing reads to the (non-existent) SPI flash window.
`addr_readable` — extended whitelist for `EMMC_BASE`, `IO_CTRL0_BASE`, and the bootrom mask ROM (`BOOTROM_BASE..+64 KiB`), each gated by per-SoC Makefile defines. The bootrom-ROM range is the source of the pinmux table; eMMC + IO ranges are needed by the driver.
`spi_flash.h` — adds `FLASH_TYPE_EMMC = 2` to the enum.
`Makefile` — adds `EMMC_BASE / IO_CTRL0_BASE / SYSCTRL_BASE / BOOTROM_BASE / BOOTROM_SIZE` under the `hi3516cv500` stanza and threads the corresponding `-D` defines into CFLAGS. `emmc_himci.c` joins `SRCS_C` only when `EMMC_BASE` is set, so non-eMMC SoCs are unaffected.
Known limitations (intentional MVP cuts)
Test plan
Gotchas captured in the PR for future debug
Followup work captured in kaeru `agent-emmc-himci-read-mvp-2026-05-15`.
🤖 Generated with Claude Code