SDIO 是在 SD 总线基础上扩展出来的外设通信接口,常用于连接 WiFi、蓝牙、GPS 等芯片。主机通过 CLK、CMD、DATA0~DATA3 等信号线与外部设备通信,其中 CLK 提供时钟,CMD 负责命令和响应,DATA0~DATA3 负责数据传输。

SDIO 框架可以按照四层来理解:Host 控制器驱动层、MMC Core 层、SDIO Core 层和 SDIO 设备功能驱动层。这四层从下到上分别负责硬件控制、总线管理、SDIO 设备识别以及具体芯片驱动。本文将围绕这四层,介绍 SDIO 通信的完整流程,并结合型号为 Ai-WS1 的 SDIO WiFi 模块,说明其驱动移植过程。
目录
1. Host 控制器驱动层
2. MMC Core 层
3. SDIO Core 层
4. SDIO 设备功能驱动层
5. Ai-WS1 WiFi 模块的 SDIO 驱动移植
1. Host 控制器驱动层
Host 控制器驱动层负责初始化 SoC 内部的 SDIO 主机控制器。以 i.MX6ULL 为例,uSDHC1 就是 SDIO Host 控制器,主要负责配置寄存器、时钟、中断和引脚复用。初始化完成后,驱动会创建并注册 struct mmc_host,将 uSDHC1 交给 MMC Core 管理。
2. MMC Core 层
MMC Core 层负责统一管理 mmc_host,包括总线上电、卡检测、设备扫描和请求调度。当 Host 控制器注册完成后,MMC Core 会开始扫描总线。例如:
CMD52:尝试复位 SDIO 功能
CMD0 :使设备回到 Idle 初始化状态
CMD8 :检查 SD 2.0+ 存储卡的接口条件和电压兼容性
3. SDIO Core 层
SDIO Core 层负责识别 SDIO 设备、枚举 Function,并匹配对应驱动。如果检测到 SDIO WiFi 设备,内核会通过 CMD5 (确定是否是sdio设备)获取设备信息和 Function 数量,然后创建对应的 struct sdio_func。接着读取每个 Function 的类型、厂商 ID 和设备 ID,用于后续匹配具体的 SDIO 设备驱动。例如:
sdio_read_fbr() -> 读取 Function 基本寄存器,填充 func->class
sdio_read_func_cis() -> 读取 Function CIS 信息,填充 func->vendor、func->device
这些信息读取完成后,SDIO Core 会调用 sdio_add_func() 将每个 Function 注册到 SDIO 总线上。随后通过 sdio_bus_match() 根据 vendor、device 等信息匹配对应的 sdio_driver。
4. SDIO 设备功能驱动层
SDIO 设备功能驱动层就是具体芯片驱动,例如 WiFi、蓝牙驱动等。当 sdio_func 和对应的 sdio_driver 匹配成功后,内核会调用驱动的 probe() 函数。驱动会在 probe() 中完成芯片初始化、固件下载、中断申请和数据收发等工作。
这些驱动通常不会直接操作 Host 控制器寄存器,而是通过标准 SDIO API 与设备通信。常用命令包括 CMD52 和 CMD53,其中 CMD52 用于读写控制寄存器,CMD53 用于批量传输固件或网络数据。
CMD52:用于读写单字节控制寄存器
CMD53:用于批量传输数据,例如固件或网络数据包
因此,SDIO 设备从硬件初始化到驱动匹配的整体流程可以概括为:
设备树 usdhc1 节点
↓
Host 控制器驱动初始化 uSDHC1
↓
注册 mmc_host
↓
MMC Core 上电并扫描总线
↓
SDIO Core 识别 SDIO 设备并枚举 Function
↓
创建并注册 struct sdio_func
↓
通过 sdio_bus_match() 匹配 WiFi sdio_driver
↓
调用 WiFi 驱动 probe()
↓
WiFi 驱动通过 CMD52、CMD53 与芯片通信
总体来说,SDIO 框架的核心思想是:底层 Host 控制器驱动负责具体硬件传输,MMC Core 负责统一管理总线和请求,SDIO Core 负责识别和枚举 SDIO Function,而具体的 SDIO 设备功能驱动则负责完成 WiFi、蓝牙等芯片的初始化和数据通信

uSDHC1 是 SoC 内部的 SDIO Host 控制器,负责真正驱动 SDIO 相关引脚完成硬件传输。
① 当主机向 WiFi 芯片发送网络数据包时,数据会先从应用程序进入 Linux 网络栈,再交给 WiFi 驱动。
② WiFi 驱动不会直接操作 uSDHC1 控制器寄存器,而是调用 Linux 内核提供的标准 SDIO API,例如 sdio_writesb()。
③ MMC Core 会将这次数据传输封装成 SDIO CMD53 请求,再通过 sdhci_request() 交给底层 Host 控制器驱动。
④ 由 uSDHC1 控制器通过 CMD、DATA0~3 等引脚把数据发送给 WiFi 芯片。
5. Ai-WS1 WiFi 模块的 SDIO 驱动移植
Ai-WS1 WiFi 模块插入 SD 卡槽使用时,从原理图可以看到它占用的是 SD1_CLK、SD1_CMD、SD1_DATA0~SD1_DATA3 和 SD1_CD。因此软件排查时,可以按照 Host 控制器驱动、MMC Core、SDIO Core、SDIO WiFi 功能驱动 这几层来分析。
① 首先检查 Host 层,也就是确认 usdhc1/mmc0 控制器是否注册成功。可以执行:
ls /sys/class/mmc_host
如果能看到:
mmc0 mmc1
说明 MMC Host 已经注册成功。一般情况下,mmc0 对应 usdhc1,也就是 SD 卡槽;mmc1 对应 usdhc2,也就是 eMMC。启动日志中如果出现类似:
sdhci-esdhc-imx 2190000.usdhc
mmc0: SDHCI controller on 2190000.usdhc
说明 usdhc1 的 Host 控制器驱动已经正常工作。
② 检查 MMC Core 和 SDIO Core 是否扫描到 SDIO 设备。正常情况下,日志中会出现:
mmc0: new high speed SDIO card at address 0001
这说明 MMC Core 已经通过 SDIO 流程识别到了设备,并完成了 SDIO card 的基本初始化。

③ SDIO WiFi 功能驱动层。
SDIO function 注册成功后,内核会通过 sdio_bus_match() 根据 vendor/device 或 class 匹配对应的 WiFi sdio_driver。匹配成功后调用 WiFi 驱动的 probe() 函数,完成芯片初始化、固件下载、中断申请和 wlan0 注册。
④ SDIO WiFi 设备移植
1、Ai-WS1 WiFi 驱动编译前,需要先修改 ./config 文件中的两个关键配置:WSCFG_CROSS_COMPILE 和 WSCFG_KERNEL_DIR。其中,WSCFG_CROSS_COMPILE 用来指定交叉编译器路径,WSCFG_KERNEL_DIR 用来指定 Linux 内核源码路径。编译时,Makefile 会进入内核源码目录,并通过 make -C <内核目录> M=<驱动目录> modules 的方式生成 WiFi 驱动的 .ko 模块。


2、执行 make platform wifi 后,主要生成 plat_soc.ko、wifi_soc.ko 和 ws73_cfg.ini。其中 .ko 是驱动模块,ws73_cfg.ini 是驱动配置文件,firmware/*.bin 固件需要另外拷贝到板端指定目录。
3、板端部署时,需要将 ws73.bin、wifi_cali.bin、btc_cali.bin、wow.bin 放到 /etc/ws73/ 目录下,将 ws73_cfg.ini 放到 /etc/ws73_cfg.ini。其中 ws73.bin 是 WiFi 芯片主固件,wifi_cali.bin 是 WiFi 校准文件,btc_cali.bin 是蓝牙/共存相关校准文件,wow.bin 是低功耗唤醒文件。
4、加载驱动时,先执行 insmod plat_soc.ko,用于读取配置、初始化平台、建立 SDIO/HCC 通道并下载固件;再执行 insmod wifi_soc.ko,用于初始化 WiFi 功能,对接 Linux 网络和 cfg80211 框架,最终注册 wlan0/wlan1 供用户使用。







