MMC/SD 驱动模型 + 实际应用解析
关键词:Linux 驱动、MMC、SD 卡、mmc_host、mmc_card、block 子系统、嵌入式系统
在嵌入式开发中,SD 卡和 eMMC 存储器是常见的非易失性存储设备。Linux 对这类设备提供了完整的驱动框架,本文将深入解析 Linux 下 MMC/SD 驱动模型的架构,并结合实际应用举例说明如何定制化适配与调试。
一、MMC/SD 驱动模型概览
1.1 整体架构
Linux 内核中,MMC/SD 驱动主要由以下三个部分组成:
-
主机控制器驱动(Host Controller Driver)
提供底层寄存器访问和传输能力。对应结构体为struct mmc_host
。 -
核心层(Core Layer)
提供协议解析、卡识别、命令封装等逻辑。对应核心文件为mmc_core.c
。 -
卡设备驱动(Card Driver)
针对具体卡类型(如 SD、eMMC、SDIO)进行处理。主要结构体为struct mmc_card
。
[ 上层 VFS ]
|
[ block 层 ]
|
[ mmc_blk.ko ]
|
[ mmc core ]
|
[ sdhci, dw_mmc, ... host 驱动 ]
|
[ SoC 寄存器操作 ]
二、核心结构体分析
2.1 mmc_host
该结构体代表一个控制器(控制器可能挂多个卡槽)。注册函数为:
struct mmc_host *mmc_alloc_host(int extra, struct device *dev);
关键字段:
ops
: 指向主机操作函数集,如request()
,set_ios()
等。caps
: 描述主机能力(是否支持高电压、DMA、HS400 等)。f_min / f_max
: 支持的最小/最大时钟频率。
2.2 mmc_card
代表一张卡(SD、eMMC、SDIO):
type
: 卡的类型(MMC_TYPE_SD, MMC_TYPE_MMC 等)ocr
: 卡支持的电压范围cid/csd/ext_csd
: 卡寄存器信息host
: 所属的mmc_host
识别过程由 mmc_rescan()
实现,会自动执行卡初始化协议流程。
2.3 mmc_driver
卡设备驱动使用:
static struct mmc_driver my_driver = {
.drv = {
.name = "my_sd_driver",
},
.probe = my_mmc_probe,
.remove = my_mmc_remove,
};
通常配合 mmc_register_driver()
注册。
三、常用主机控制器驱动
3.1 sdhci(标准主机控制器接口)
用于符合 SD Host Controller 规范的控制器,支持通用的寄存器访问方法:
- 驱动文件:
drivers/mmc/host/sdhci.c
- 常见平台:高通、NXP、TI 等
- 平台设备名:
sdhci-msm
,sdhci-tegra
,sdhci-pci
等
3.2 dw_mmc(DesignWare 控制器)
用于 Synopsys 的 IP,常见于 Rockchip、Samsung:
- 驱动文件:
drivers/mmc/host/dw_mmc.c
四、实际平台适配案例:定制 eMMC 支持
4.1 设备树配置(以高通 QRB5165 平台为例)
&sdhc_1 {
status = "okay";
mmc-hs400-1_8v;
bus-width = <8>;
non-removable;
cap-mmc-highspeed;
};
关键属性说明:
non-removable
: eMMC 固连,非热插拔bus-width
: 总线宽度,eMMC 一般为 8bitmmc-hs400-1_8v
: 表示支持 HS400 模式
4.2 调试流程
# 查看设备是否挂载成功
ls /dev/mmcblk*
# 查看卡信息
cat /sys/class/mmc_host/mmc0/mmc0:0001/name
cat /sys/class/mmc_host/mmc0/mmc0:0001/ext_csd
# 查看主机控制器属性
cat /sys/class/mmc_host/mmc0/clock
cat /sys/class/mmc_host/mmc0/caps
五、自定义卡设备驱动(比如 SDIO Wi-Fi)
5.1 编写驱动
static const struct sdio_device_id my_wifi_ids[] = {
{ SDIO_DEVICE(0x02DF, 0x9123) },
{ /* sentinel */ }
};
static struct sdio_driver my_wifi_driver = {
.name = "my_wifi",
.id_table = my_wifi_ids,
.probe = my_wifi_probe,
.remove = my_wifi_remove,
};
5.2 注册驱动
module_sdio_driver(my_wifi_driver);
六、常见问题与调试建议
问题 | 可能原因 | 解决建议 |
---|---|---|
/dev/mmcblk0 不出现 | 没有识别到卡 | 检查设备树配置与电压时序 |
频繁超时/CRC 错误 | 电源不稳,线缆质量差 | 检查 PMIC、电源轨 |
读写速度慢 | 时钟未配置、未启用 DMA | 开启高速模式,调大 f_max |
文件系统损坏 | 热插拔、突然掉电 | 选择合适的文件系统,如 ext4 + journaling |
七、结语
MMC/SD 驱动是 Linux 存储子系统中的重要组成,理解其框架有助于快速定位问题与平台适配。无论是使用标准控制器如 SDHCI,还是开发 SDIO 设备驱动,只要掌握了 mmc_host
和 mmc_card
的核心机制,配合内核日志和 sysfs 接口调试,将事半功倍。