4. Linux SPI 子系统架构:SPI 核心层、SPI 控制器驱动层、SPI 设备驱动层、SPI 设备树绑定
在嵌入式 Linux 系统中,SPI(Serial Peripheral Interface)子系统采用经典的分层架构设计,将协议处理、硬件控制与设备逻辑解耦。理解这一架构是全志 T113 SPI Flash 驱动适配与性能调优的基础。本章从整体框架出发,逐层剖析 SPI 核心层、控制器驱动层、设备驱动层以及设备树绑定的职责与交互机制。
架构核心思想: Linux SPI 子系统通过分层抽象,使得 SPI 控制器驱动(硬件相关)与 SPI 设备驱动(协议相关)可以独立开发与维护。设备树则充当硬件拓扑的描述语言,将两者在运行时绑定。
4.1 SPI 子系统整体分层架构
SPI 子系统从上到下分为三层:SPI 设备驱动层、SPI 核心层、SPI 控制器驱动层。设备树通过描述 SPI 控制器与从设备的连接关系,驱动核心层在初始化时完成匹配与注册。
关键理解: 在全志 T113 平台上,SPI Flash 驱动通常位于设备驱动层(如 m25p80.c 或 spi-nor 框架),通过 SPI 核心层调用控制器驱动层提供的硬件接口完成数据收发。设备树文件(.dts)中的 spi0 节点描述了控制器基地址、时钟、DMA 以及连接的 Flash 芯片信息。
4.2 SPI 核心层(SPI Core)
SPI 核心层位于 drivers/spi/spi.c 中,是整个子系统的中枢。它负责以下关键功能:
- 总线注册与管理: 注册 SPI 总线类型(
spi_bus_type),管理所有 SPI 控制器与设备。 - 设备与驱动匹配: 当设备树解析出 SPI 设备节点后,核心层根据
compatible属性匹配对应的spi_driver。 - 数据传输队列: 提供
spi_async()、spi_sync()接口,管理消息队列并调度控制器驱动完成传输。 - SPI-MEM 抽象层: 针对 SPI 存储设备(如 NOR Flash)提供
spi_mem_ops接口,简化读写操作。
| 核心接口/数据结构 | 所在文件 | 功能描述 |
|---|---|---|
struct spi_controller |
spi.h | 代表一个 SPI 控制器,包含传输方法、DMA 配置、时钟等 |
struct spi_device |
spi.h | 代表一个 SPI 从设备,包含模式、速度、字长等参数 |
struct spi_message |
spi.h | 一次 SPI 传输的完整描述,包含多个 spi_transfer |
spi_register_controller() |
spi.c | 控制器驱动调用,将控制器注册到核心层 |
spi_sync() |
spi.c | 同步阻塞式 SPI 数据传输 |
spi_async() |
spi.c | 异步非阻塞式 SPI 数据传输 |
性能提示: 在 SPI Flash 读写场景中,核心层的消息队列调度直接影响吞吐量。全志 T113 平台建议使用
spi-mem 接口(spi_mem_exec_op()),它针对存储设备优化了命令/地址/数据阶段的组合传输,减少消息拆分开销。
4.3 SPI 控制器驱动层
控制器驱动层直接操作硬件寄存器,实现 SPI 总线的时序控制。对于全志 T113 平台,控制器驱动通常位于 drivers/spi/spi-sunxi.c(或类似命名)。
控制器驱动需要实现的核心回调函数:
master_transfer()/transfer_one_message():执行单个 SPI 消息的传输。setup():配置 SPI 设备的模式(CPOL/CPHA)、位宽、时钟频率。prepare_message()/unprepare_message():传输前后的准备与清理。can_dma():判断当前传输是否适合使用 DMA。
全志 T113 控制器特性: T113 的 SPI 控制器支持 4 个片选、8/16/32 位数据宽度、内置 64 字节 TX/RX FIFO,并支持硬件 DMA 传输。在调优时,合理配置 SPI 时钟频率(通常 50MHz~100MHz)和启用 DMA 是提升读写性能的关键。
4.4 SPI 设备驱动层
设备驱动层实现具体的 SPI 设备协议。对于 SPI NOR Flash,内核提供了 drivers/mtd/spi-nor/ 框架,其中 spi-nor.c 和 m25p80.c 是核心文件。
设备驱动通过 spi_driver 结构体注册到核心层:
static struct spi_driver m25p80_driver = {
.driver = {
.name = "m25p80",
.of_match_table = m25p_ids, // 设备树 compatible 匹配表
},
.probe = m25p_probe,
.remove = m25p_remove,
.id_table = m25p_ids,
};
module_spi_driver(m25p80_driver);
设备驱动的主要职责:
- 探测(probe): 读取 Flash ID,识别芯片型号,初始化 MTD 设备。
- 读写操作: 通过
spi_mem_ops或直接构造spi_message发送 SPI 命令(如 Read、Page Program、Erase)。 - 分区管理: 解析设备树中的
partitions节点,注册 MTD 分区。
| 设备驱动文件 | 适用场景 | 关键接口 |
|---|---|---|
m25p80.c |
通用 SPI NOR Flash(经典框架) | m25p80_read() / m25p80_write() |
spi-nor.c |
现代 SPI NOR Flash 统一框架 | spi_nor_read() / spi_nor_write() |
spi-mem.c |
SPI 存储设备抽象层(推荐) | spi_mem_exec_op() |
适配建议: 在全志 T113 上适配 W25Q128 等 Flash 时,优先使用
spi-nor 框架 + spi-mem 接口。这种方式可以充分利用控制器驱动的 DMA 能力,并且代码维护性更好。
4.5 SPI 设备树绑定
设备树(Device Tree)是 SPI 子系统硬件拓扑的描述语言。全志 T113 的设备树文件通常位于 arch/arm/boot/dts/sun8i-t113*.dts 中。
一个典型的 SPI 控制器节点及其 Flash 子节点如下:
&spi0 {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
cs-gpios = <&pio PC 3 GPIO_ACTIVE_LOW>; // 片选 GPIO
flash@0 {
compatible = "jedec,spi-nor"; // 通用 SPI NOR Flash 匹配
reg = <0>; // 片选索引 0
spi-max-frequency = <80000000>; // 最大 SPI 时钟 80MHz
spi-rx-bus-width = <4>; // 四线读取(QSPI 模式)
spi-tx-bus-width = <4>;
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "boot";
reg = <0x000000 0x100000>; // 1MB 启动分区
};
partition@1 {
label = "rootfs";
reg = <0x100000 0x700000>; // 7MB 根文件系统
};
};
};
};
设备树绑定的关键属性说明:
| 属性 | 说明 | 典型值 |
|---|---|---|
compatible |
驱动匹配字符串,核心层据此查找对应的 spi_driver |
"jedec,spi-nor" 或 "w25q128" |
reg |
片选编号,从 0 开始 | <0> |
spi-max-frequency |
SPI 总线最高时钟频率(Hz) | <80000000> |
spi-rx-bus-width |
接收数据总线宽度(1/2/4 线) | <4> 启用 QSPI 四线模式 |
spi-tx-bus-width |
发送数据总线宽度 | <4> |
cs-gpios |
片选 GPIO 控制(在控制器节点中定义) | <&pio PC 3 GPIO_ACTIVE_LOW> |
常见错误: 设备树中
spi-max-frequency 设置过高(超过 Flash 芯片或控制器支持上限)会导致通信不稳定或数据错误。全志 T113 的 SPI 控制器最高通常支持 100MHz,但 W25Q128 等 Flash 在四线模式下建议不超过 80MHz。务必参考芯片数据手册确认。
4.6 本章小结
Linux SPI 子系统的分层设计为全志 T113 平台上的 SPI Flash 驱动适配提供了清晰的框架:
- SPI 核心层 提供总线管理与传输调度,是上下层的桥梁。
- SPI 控制器驱动层 直接操作 T113 硬件寄存器,实现底层时序。
- SPI 设备驱动层 实现 Flash 协议,通过 MTD 层向用户空间提供存储接口。
- 设备树绑定 将硬件拓扑与驱动匹配规则静态描述,实现即插即用。