Linux SDHCI 驱动解析:硬件原理与核心机制全解

sdhci.c 是 Linux 内核中针对 SD Host Controller Interface(简称 SDHCI)控制器的通用驱动核心模块。它支持绝大多数符合 SDHCI 标准的硬件控制器,实现了对 SD、eMMC、SDIO 等设备的读写控制。在本文中,我们将结合源码,从硬件规范角度深入剖析其核心机制。
在这里插入图片描述

一、SDHCI 是什么?

SDHCI(Secure Digital Host Controller Interface)是一种主机控制器接口标准,由 SD 协会定义,旨在统一 SD 卡控制器与系统主机之间的软件接口。它通常部署在 SoC 或主板芯片组中,负责与 SD 卡之间的通信,支持:

  • 标准 SD 和 SDHC/SDXC 卡
  • eMMC 存储芯片(部分兼容)
  • SDIO 外设(如无线模块)

二、寄存器布局与硬件抽象

SDHCI 控制器通过一组统一寄存器与 CPU 通信。常见的寄存器包括:

寄存器名称功能描述
SDHCI_ARGUMENT命令参数
SDHCI_COMMAND命令与响应类型控制
SDHCI_RESPONSE命令响应寄存器
SDHCI_TRANSFER_MODE传输模式设置(DMA、多块等)
SDHCI_PRESENT_STATE当前状态(总线忙、卡插入等)
SDHCI_CLOCK_CONTROL时钟启用与分频
SDHCI_HOST_CONTROL主控功能控制,如数据宽度、HighSpeed
SDHCI_POWER_CONTROL电压设定与电源开关

驱动通过 sdhci_readl()sdhci_writel() 等封装函数与寄存器交互,实现硬件无关性。

三、初始化与卡检测

驱动初始化时,sdhci_init() 会进行控制器复位,并设置中断、清除旧状态等:

sdhci_reset(host, SDHCI_RESET_ALL);
sdhci_clear_set_irqs(...);
sdhci_set_ios(...);  // 设置电压、时钟、数据宽度

随后调用 sdhci_enable_card_detection() 启用卡插拔检测逻辑。检测方式通常有两种:

  • 电平检测(读取 PRESENT_STATE
  • 中断检测(依赖 CARD_INSERTCARD_REMOVE 中断)

部分控制器存在卡检测问题(如 SDHCI_QUIRK_BROKEN_CARD_DETECTION),驱动中也通过 quirk 机制予以规避。

四、命令发送机制(Command Path)

MMC 协议中,每次传输前都需发出命令(CMDx)。命令发送通过 sdhci_send_command() 实现:

  1. 等待控制器空闲(检查 CMD_INHIBITDATA_INHIBIT
  2. 写入命令参数:SDHCI_ARGUMENT
  3. 设置传输模式(Transfer Mode):读/写、多块、DMA
  4. 写入命令寄存器:SDHCI_COMMAND
  5. 启动定时器防止卡死

中断响应由 sdhci_cmd_irq() 处理,解析响应并填充 mmc_commandresp[] 字段。

五、数据传输机制:PIO 与 DMA

SDHCI 控制器支持三种数据传输方式:

  • PIO 模式:CPU 轮询或中断,读写 SDHCI_BUFFER

    • sdhci_read_block_pio()
    • sdhci_write_block_pio()
  • SDMA(Simple DMA)

    • 支持一次性 DMA 传输,使用 SDHCI_DMA_ADDRESS
    • 配合 SG 列表,驱动仅支持单个段,限制大
  • ADMA(Advanced DMA)

    • 使用 ADMA descriptor table:sdhci_adma_table_pre/post()
    • 可自动遍历 SG 列表,性能高

驱动通过 host->flags 记录当前使用的传输方式,若 DMA 条件不满足(如未对齐、长度限制),则自动回退至 PIO。

六、时钟控制机制

时钟控制由 sdhci_set_clock() 完成,其核心思路是:

  • 按目标频率计算分频值(div
  • 写入 SDHCI_CLOCK_CONTROL,使能内部时钟
  • 等待 INT_CLOCK_STABLE 标志
  • 启用卡时钟输出

在 UHS 模式或 Preset Value 启用场景下,还需配合 HOST_CONTROL2 寄存器更新。

七、电压控制与信号电平切换

控制器可支持 3.3V / 1.8V 的 IO 电压切换,流程如下:

  1. 关闭 SDCLK 输出
  2. 修改 HOST_CONTROL2 中的 VDD 电压位
  3. 延迟等待电平稳定
  4. 重新启用 SDCLK
  5. 检查数据线电平(DAT[3:0])

若切换失败,需重新上电(power cycle)卡片。

八、中断处理

中断处理函数为 sdhci_irq(),主要分为:

  • 命令中断:sdhci_cmd_irq()
  • 数据中断:sdhci_data_irq()
  • 卡插拔中断:通过 CARD_INSERT/REMOVE 标志调度 tasklet
  • SDIO 中断:通过 CARD_INT 标志,回调 mmc_signal_sdio_irq()

对于 DMA、PIO、卡状态变化等情况,均通过中断+tasklet 模式完成异步处理,提升效率并避免死锁。

九、调试与寄存器分析

驱动提供 sdhci_dumpregs() 函数用于输出关键寄存器值,便于调试卡识别、数据异常等问题。典型输出如:

sdhci: =========== REGISTER DUMP ===========
Sys addr: 0x00000000 | Version:  0x00003000
Blk size: 0x00000200 | Blk cnt:  0x00000008
...

建议在调试中插入关键路径调用以观察寄存器状态变化。

十、总结:SDHCI 驱动的关键价值

SDHCI 作为标准控制器驱动,其核心价值在于封装控制器访问规范屏蔽平台差异性优化传输性能。通过 quirks、ops 等机制,它既支持通用性,又能灵活适配特定硬件。

对嵌入式开发者而言,理解 SDHCI 驱动的硬件控制机制有助于:

  • 定位卡识别失败、挂载问题
  • 优化高速模式下的数据传输性能
  • 进行平台适配或自研控制器移植

如果你还希望扩展博文内容至移植过程分析DMA 调试技巧,我可以继续完善。如果需要插图,我也可配合绘制 SDHCI 控制器结构或时序图。需要我继续扩展某部分吗?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值