SD/MMC/eMMC 驱动
本文档介绍 RK3588 SDMMC / eMMC 控制器在 Linux 6.1 内核中的驱动配置、用户态调试和分区管理。
适用范围: RK3588 Linux 6.1 Debian 12 / Ubuntu 22.04 系统,C-3588LQ V1.0 + SHIMETAPI-M5-R2A V1.0 底板。
1. 概念基础
1.1 存储接口类型
RK3588 包含多种存储控制器:
| 接口 | 速率 | 用途 |
|---|---|---|
| eMMC 5.1 | HS400 最高 400 MB/s | 系统存储 |
| SD 3.0 | UHS-I 最高 104 Mbps | SD 卡扩展 |
| SDIO 3.0 | — | WiFi / 蓝牙模块 |
1.2 控制器基地址
| 控制器 | 基地址 | 用途 |
|---|---|---|
| eMMC | 0xfe2e0000 | DWCMHSC SDHCI |
| SDMMC | 0xfe2b0000 | DW-MSHC SD 卡 |
| SDIO0 | 0xfe310000 | DW-MSHC SDIO WiFi/BT |
本机
ls /sys/class/mmc_host/显示mmc0 / mmc1 / mmc2,对应三条通道。
2. 准备工作
2.1 硬件清单
| 组件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | C-3588LQ 核心板 + SHIMETAPI-M5-R2A 底板 | 1 | 核心板内置 eMMC |
| 调试串口线 | USB 转 TTL(3.3V) | 1 | 波特率 1500000 |
| Micro SD 卡 | 16GB+ Class 10 | 1 | SD 卡测试 |
出厂默认未装 SD 卡槽,依靠核心板 eMMC 启动。本节以 eMMC 为主,SD 卡用法类似。
3. 软件准备
3.1 内核配置
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_OF=y
CONFIG_OF_MMC=y3.2 设备树
/* eMMC */
sdhci: sdhci@fe2e0000 {
compatible = "rockchip,dwcmshc-sdhci", "snps,dwcmshc-sdhci";
reg = <0x0 0xfe2e0000 0x0 0x10000>;
interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru CLK_EMMC>, <&cru PCLK_EMMC>,
<&cru CCLK_SRC_EMMC>, <&cru SCLK_SFC_EMMC>,
<&cru HCLK_EMMC>;
clock-names = "core", "axi", "block", "fio", "ahb";
resets = <&cru SRST_EMMC>;
reset-names = "emmc";
status = "okay";
};
/* SDMMC(SD 卡) */
sdmmc: dwmmc@fe2b0000 {
compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
reg = <0x0 0xfe2b0000 0x0 0x4000>;
interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru HCLK_SDMMC>, <&cru CLK_SDMMC>,
<&cru SCLK_SDMMC>;
clock-names = "ciu", "biu", "ciu-div";
fifo-depth = <0x100>;
max-frequency = <150000000>;
status = "okay";
};
/* SDIO0 */
sdio0: dwmc@fe310000 {
compatible = "rockchip,rk3588-dw-mshc";
reg = <0x0 0x310000 0x0 0x4000>; /* 占位,实际以 SDK 为准 */
status = "disabled";
};4. 设备端 eMMC 信息
4.1 块设备列表
lsblk实机输出如下:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
mmcblk0 179:0 0 29.2G 0 disk
├─mmcblk0p1 179:1 0 4M 0 part
├─mmcblk0p2 179:2 0 4M 0 part
├─mmcblk0p3 179:3 0 64M 0 part
├─mmcblk0p4 179:4 0 128M 0 part
├─mmcblk0p5 179:5 0 32M 0 part
├─mmcblk0p6 179:6 0 14G 0 part /
├─mmcblk0p7 179:7 0 128M 0 part /oem
└─mmcblk0p8 179:8 0 14.8G 0 part /userdata
mmcblk0boot0 179:32 0 4M 1 disk
mmcblk0boot1 179:64 0 4M 1 disk出厂镜像分区:mmcblk0p6 是 rootfs(/),p7 是 /oem(厂商数据),p8 是 /userdata。
4.2 eMMC 型号
cat /sys/block/mmcblk0/device/name输出输出:
TA28324.3 eMMC CID(卡识别号)
cat /sys/block/mmcblk0/device/cid输出输出:
700100544132383332221676a59027004.4 eMMC 容量(扇区 × 512)
cat /sys/block/mmcblk0/size输出输出:
61145088换算一下:61145088 × 512 ÷ 1024³ ≈ 29.2 GB,和上面 lsblk 显示的容量一致。
4.5 eMMC 当前总线模式
cat /sys/kernel/debug/mmc0/ios输出示例:
clock: 198000000 Hz
actual clock: 198000000 Hz
vdd: 21 (3.3V)
bus mode: 2 (hs400)
timing: 5 (ddr52)
signal voltage: 1 (1.80 V)
driver type: 0 (driver type B)4.6 SD 卡操作(若无 SD 卡可跳过)
# 插入 SD 卡后查看
cat /sys/block/mmcblk1/device/name
cat /sys/block/mmcblk1/size
# 格式化为 ext4
mkfs.ext4 /dev/mmcblk1p1
# 挂载
mkdir -p /mnt/sd
mount /dev/mmcblk1p1 /mnt/sd
df -h /mnt/sd
# 卸载
umount /mnt/sd5. 分区操作(eMMC)
5.1 查看分区
fdisk -l /dev/mmcblk0
parted /dev/mmcblk0 print5.2 烧录镜像(PC 端 → eMMC)
[电脑端] 通过 USB OTG 用 fastboot/RKDevTool 烧录:
# 设备进入 Loader 模式(按住 Recovery 键 + 上电)
fastboot flash mmc0 update.img[电脑端] 另一种方式是用 dd 直接烧(这条命令在开发板侧执行,需要 root,请谨慎):
dd if=update.img of=/dev/mmcblk0 bs=4M status=progress
sync5.3 速度测试
用下面的命令分别测顺序读和顺序写:
# 顺序读
hdparm -t /dev/mmcblk0p6
# 顺序写(如无用途请勿生产环境跑)
dd if=/dev/zero of=/mnt/test bs=1M count=100 oflag=direct6. 代码解读
6.1 驱动注册
// drivers/mmc/host/dw-mshc-rockchip.c(简化)
static struct platform_driver rockchip_dwcmshc_driver = {
.probe = rockchip_dwcmshc_probe,
.remove = rockchip_dwcmshc_remove,
.driver = {
.name = "rockchip-dwcmshc",
.of_match_table = rockchip_dwcmshc_match,
},
};
static const struct of_device_id rockchip_dwcmshc_match[] = {
{ .compatible = "rockchip,dwcmshc-sdhci" },
{ /* sentinel */ }
};6.2 块设备读取链路
用户空间: cat /mnt/test
→ VFS 读取
→ ext4_file_read_iter() /* ext4 文件系统 */
→ submit_bh() /* 块层 */
→ mmc_queue_read() /* MMC 队列 */
→ mmc_blk_data_complete()
→ dw_mci_request() /* Rockchip DW-MSHC 驱动 */
→ 设置 SDMMC 寄存器 / DMA 描述符
→ 硬件总线传输7. 故障排除
7.1 eMMC 不识别
先看内核日志、调试节点和设备树状态:
dmesg | grep -i mmc
ls /sys/kernel/debug/mmc0
cat /proc/device-tree/soc/sdhci@fe2e0000/status # 应 = "okay"7.2 速度慢
# 检查当前协商模式(应 = HS400 / DDR52)
cat /sys/kernel/debug/mmc0/ios
# 重新插卡触发 reset
# 检查线缆 / 焊接不良7.3 坏块 / 寿命耗尽
# 健康度(EMMC 6.0+ 协议)
cat /sys/block/mmcblk0/device/pre_eol_info
cat /sys/block/mmcblk0/device/life_time_est_typ_alife_time_est_typ_a = 0x01~0x0A(A 级寿命参考),达 0x0A 即接近寿命终了。
