Linux MMC子系统2(基于Linux6.6)---驱动模型介绍
本模块主要介绍MMC子系统与设备-总线-驱动模型的关联,并介绍该MMC子系统是如何借助LINUX内核的设备-总线-驱动模型实现自己的驱动模型的。针对MMC子系统而言,主要使用了系统中的两个模型:设备-总线-驱动模型、块设备驱动模型。
一、设备-总线-驱动模型
在分析MMC子系统的设备-总线-驱动模型时,针对复杂的设备,则需要借助控制器进行通信,而针对i2c、spi、mmc而言,均需要对应的控制器实现与该类设备的通信。而针对这三类控制器,其模块都进行了抽象,其中i2c控制器抽象为i2c adapter、spi控制器抽象为spi master,而针对mmc控制器,则抽象为mmc host;而针对这三种类型设备的抽象,i2c设备抽象为i2c client、spi设备抽象为spi device、mmc device抽象为mmc card。
下面分析下这三类驱动模型的异同:
方面 | I2C 驱动模型 | SPI 驱动模型 | MMC 驱动模型 |
---|---|---|---|
协议类型 | 逐字节的串行通信协议,基于主从模式。 | 全双工串行通信协议,基于主从模式,通常有多个从设备。 | 存储卡接口,支持不同的存储设备(如SD卡、eMMC)。 |
硬件接口 | 使用2根信号线:数据线(SDA)和时钟线(SCL)。 | 使用4根信号线:MOSI、MISO、SCK、CS(片选)。 | 使用多种接口,如SDHCI、MMC主机控制器,数据和时钟信号。 |
传输速率 | 较低,通常最高传输速率为400 Kbps(标准模式)至3.4 Mbps(高速模式)。 | 较高,通常为几Mbps到几十Mbps,支持全双工传输。 | 速度较高,通常取决于MMC卡类型(如eMMC、SD卡等),可支持数百Mbps。 |
数据传输单位 | 按字节传输,每次传输一个字节的数据。 | 数据传输单位是一个字或多个字节,支持全双工传输。 | 数据传输单位是块(通常为512字节),读取和写入都是基于块操作的。 |
硬件控制方式 | I2C总线上的所有设备由主控制,设备的地址唯一。 | SPI总线上的每个设备通过片选(CS)信号控制,不同设备可以共享相同的总线。 | MMC设备通常通过SDHCI或自定义主机控制器与系统通信。 |
驱动架构 | I2C设备驱动主要由 i2c-core 和各个 i2c-driver 组成,使用 I2C设备树或 i2c_adapter 进行管理。 | SPI设备驱动通过 spi-core 和具体的 spi-driver 管理。每个SPI设备通过 spi_device 进行管理。 | MMC驱动通常由 mmc-core 、mmc-block 和 host 驱动组成,支持 MMC 主机控制器、SD卡和eMMC设备。 |
设备树支持 | I2C设备需要在设备树中指定设备信息,并绑定到I2C总线。 | SPI设备同样需要在设备树中定义,并通过片选选择连接的设备。 | MMC设备通过 mmc_host 和相关设备树配置进行管理和初始化。 |
总线管理 | I2C总线由主设备和多个从设备组成,每个从设备通过唯一的地址识别。 | SPI总线允许多个从设备通过独立的片选信号与主设备通信。 | MMC设备通过MMC总线连接,支持多个MMC卡设备在不同的主机控制器上。 |
传输控制 | 通过 i2c_transfer 等函数控制数据传输,支持同步和异步操作。 | 通过 spi_transfer 控制数据传输,支持同步和异步操作。 | 通过 mmc_start_request 等函数进行请求处理,支持多种I/O操作。 |
设备类型 | 通常用于传感器、时钟、EEPROM、音频编解码器等低速设备。 | 用于高速设备,如屏幕、存储设备、网络模块等。 | 用于存储设备,如SD卡、eMMC卡、UFS卡等。 |
电源管理 | 电源管理通常通过 i2c_driver 中的回调函数实现。 | SPI驱动中也有电源管理接口,通过 spi_driver 进行管理。 | MMC卡通常支持热插拔,电源管理由主机控制器和驱动实现。 |
主要接口函数 | - i2c_transfer() <br> - i2c_add_driver() <br> - i2c_del_driver() | - spi_sync() <br> - spi_async() <br> - spi_setup() | - mmc_start_request() <br> - mmc_register_driver() <br> - mmc_set_ios() |
传输方式 | 单向传输(主机写从机,或者从机响应主机)。 | 支持全双工(同时发送和接收数据)。 | 双向传输(读取/写入块设备)。 |
缓存管理 | 一般使用缓冲区传输数据,支持缓存对齐。 | 使用SPI缓冲区处理数据,通常为直接内存访问(DMA)。 | MMC卡驱动通常会使用DMA进行数据传输,并进行缓存对齐管理。 |
驱动模块加载 | I2C驱动模块可以通过 modprobe 等工具动态加载。 | SPI驱动模块也可以通过 modprobe 等工具动态加载。 | MMC驱动模块同样通过动态加载(如 modprobe mmc_core )进行。 |
总结:
-
相似之处:
- 主从模式:I2C、SPI 和 MMC 都支持主从结构,但它们的硬件接口和协议有所不同。
- 设备树支持:这三种协议都需要在设备树中定义,以确保内核正确识别和配置硬件。
- 异步操作:它们都支持异步操作,通过传输队列和回调机制管理数据传输。
-
不同之处:
- 传输方式:I2C为单向传输(主设备发送/接收数据),而SPI支持全双工通信,MMC则基于块传输。
- 硬件接口:I2C只有2根线(SDA/SCL),SPI有4根线(MOSI、MISO、SCK、CS),而MMC支持更多的信号线和更复杂的硬件接口。
- 驱动架构:每种协议的驱动模型都有不同的层次结构,I2C和SPI主要是驱动适配器和设备,而MMC则涉及更复杂的主机控制器和块设备处理。
从mmc子系统设备-驱动-总线模型间数据结构体之间的关联,来进一步分析mmc子体系的驱动模型。
1.1、mmc子系统设备-总线-驱动模型
如下即为mmc_bus_type、mmc_card、mmc_host、mmc_driver、kset、kobject的关联如下图。其中i2cbus、mmc bus、spi总线均通过其对应的kobject完成关联。而mmc host与mmc card通过其指针成员完成了绑定,而mmc card、mmc driver、mmc bus则借助设备-总线-驱动模型的数据结构完成了关联操作。
1.2、mmc子系统mmc host与mmc class的关联
mmc子系统的mmc host借助其device类型的程序class_dev以及device-class模型的数据结构完成了绑定操作,如下为mmc host与mmc class的关联,同时mmc host借助kref、mmc_class->dev_release接口,可完成mmc host变量的动态释放(当mmc_host的引用计数为0后,则会调用device_release接口进行释放操作,最终调用mmc_host_classdev_release接口,完成mmc_host的内存释放)。
1.3、mmc子系统的逻辑架构
针对mmc子系统内部,其与上层应用以及底层设备的关联如下图所示:
1. MMC Block部分
- 作用:MMC Block部分主要提供对存储卡(如SD卡、eMMC等)上数据块的访问,它在MMC子系统中扮演了类似磁盘的角色。
- 功能:实现对MMC设备的读写操作,通常作为块设备(block device)来管理,通过Linux的块设备接口提供文件系统(如FAT、ext4等)的支持。
- 驱动实现:通过
mmcblk
驱动将MMC设备暴露给用户空间,使得它们可以作为标准的块设备进行操作。mmcblk
驱动负责将底层的MMC设备转化为块设备。
2. Core接口层
- 作用:核心接口层提供了MMC子系统的核心功能,处理设备管理、卡识别、卡初始化等基础功能。
- 功能:
- 管理和识别MMCs的插入/拔出。
- 实现MMC设备的初始化、配置等基础操作。
- 提供与硬件相关的控制命令接口。
- 模块:MMC核心模块位于
drivers/mmc/core
目录,包含mmc_core.c
等文件,提供MMC设备的创建、销毁、初始化等操作。
3. Host相关接口
- 作用:Host部分是控制MMC设备访问的硬件接口层。它提供对不同MMC控制器(例如SD卡控制器、eMMC控制器)的支持。
- 功能:
- 提供硬件控制接口,确保主机和MMC卡之间的通信。
- 管理与卡的连接、数据传输的时序。
- 模块:包括
host
控制器的驱动程序,它通过mmc_host
结构与其他层次进行交互。每个主机控制器的驱动都需要实现一些基础的操作函数。 - 驱动:主机驱动通常会注册到
mmc_register_host()
函数中,负责初始化、配置硬件控制器,进行卡初始化等操作。
4. MMC/SD ops接口
- 作用:
MMC/SD ops
接口是MMC子系统和SD卡(包括SDIO卡)之间的操作接口,它提供了SD卡相关的操作接口。 - 功能:
- 定义SD卡的操作(如读写命令、初始化命令等)。
- 提供SD卡特有的操作,如不同容量、速度等级的SD卡的配置。
- 模块:在MMC子系统中,SD卡相关的操作通常会通过
sd_ops
或类似的接口定义,SD卡的操作会调用sd_ops
中定义的函数。
5. MMC bus ops接口
- 作用:提供一个抽象层,用于管理与MMC总线(如SDIO总线)相关的操作。它负责不同MMC总线控制器之间的统一操作接口。
- 功能:
- 管理MMC卡与主机之间的数据传输。
- 定义总线控制接口。
- 接口定义:在MMC子系统中,总线操作函数会通过
mmc_bus_ops
接口进行注册和实现,提供与硬件相关的总线操作,如数据传输、时序控制等。
6. MMC/SDIO bus接口
- 作用:SDIO(Secure Digital Input Output)是MMC的一种扩展,用于提供如Wi-Fi、蓝牙等设备的支持。MMC/SDIO bus接口主要负责处理与SDIO设备的通信。
- 功能:
- 提供与SDIO设备的交互接口。
- 处理SDIO卡的识别、初始化、读写等操作。
- 模块:SDIO总线接口通常在
drivers/mmc/host
中有相关实现,具体接口会通过sdio_ops
来支持。
7. MMC core接口
- 作用:MMC core接口是MMC子系统的核心接口,它抽象了对MMC设备的操作,提供了一套统一的API接口,供上层调用。
- 功能:
- 提供设备管理和控制接口,处理设备的插拔、状态检测、卡初始化等任务。
- 通过与主机驱动、SD卡驱动、文件系统等模块的交互,实现完整的MMC设备功能。
- 接口定义:MMC core通过
mmc_ops
(例如mmc_get_card()
)提供对外接口,涵盖MMC卡的操作和管理。
典型的MMC架构图(逻辑关系):
+--------------------------------------+
| User Space / File System |
| (e.g., mounting MMC/SD card) |
+--------------------------------------+
^
|
+--------------------------------------+
| MMC Block Layer |
| (blkdev - block device interface) |
+--------------------------------------+
^
|
+--------------------------------------+
| MMC Core (drivers/mmc/core) |
| (card management, initialization)|
+--------------------------------------+
^
|
+--------------------------------------+
| Host Controller Driver (e.g., SDHC)|
| (handles bus interface) |
+--------------------------------------+
^
|
+--------------------------------------+
| Bus and Device Operations |
| (MMC/SD/SDIO bus, ops interfaces) |
+--------------------------------------+
^
|
+--------------------------------------+
| Hardware (Host Controller) |
| (SDIO, SDHC, etc.) |
+--------------------------------------+