3. SPI控制器节点配置
SPI控制器节点是设备树中描述SPI主机硬件能力的核心节点。它向内核传递控制器的寄存器基址、中断号、时钟频率、DMA通道等关键资源信息,是后续从设备枚举与通信的基础。本节详细解析SPI控制器节点的三大核心属性:compatible、reg、interrupts,并辅以完整节点示例。
3.1 SPI控制器节点属性总览
一个典型的SPI控制器节点通常包含以下属性,其中前三个为必选属性:
| 属性名 | 类型 | 必选 | 说明 |
|---|---|---|---|
compatible |
字符串列表 | 是 | 匹配驱动与硬件,格式为"厂商,型号" |
reg |
地址/长度对 | 是 | 控制器寄存器基址与映射范围 |
interrupts |
中断描述 | 是 | 控制器中断号与触发类型 |
clocks |
phandle列表 | 推荐 | SPI模块时钟与PCLK时钟 |
dmas |
phandle+参数 | 可选 | DMA传输通道描述 |
#address-cells |
u32 | 是 | 子节点地址宽度,SPI总线通常为1 |
#size-cells |
u32 | 是 | 子节点地址长度,SPI总线通常为0 |
#address-cells = <1> 和 #size-cells = <0> 是SPI总线节点的固定搭配,表示每个从设备使用一个32位整数作为片选编号,且不占用地址空间范围。
3.2 compatible属性:驱动匹配的钥匙
compatible 属性是设备树与驱动代码之间的绑定契约。内核通过该属性查找已注册的 platform_driver 或 spi_controller_driver,完成硬件与驱动的匹配。
属性值采用 "厂商,型号" 格式,厂商名使用小写字母,型号与数据手册一致。推荐同时提供兼容性回退字符串:
compatible = "fsl,imx6ul-ecspi", "fsl,imx6q-ecspi";
匹配优先级:内核先尝试第一个字符串 fsl,imx6ul-ecspi,若未找到驱动则尝试第二个 fsl,imx6q-ecspi。这种设计允许同一驱动兼容多个硬件版本。
| SoC平台 | compatible字符串 | 对应驱动文件 |
|---|---|---|
| i.MX6UL | fsl,imx6ul-ecspi |
spi-imx.c |
| STM32MP1 | st,stm32h7-spi |
spi-stm32.c |
| Zynq-7000 | xlnx,zynq-spi-r1p6 |
spi-zynq-qspi.c |
| AM335x | ti,am3352-spi |
spi-omap2-mcspi.c |
"fsl, imx6ul-ecspi" 会导致驱动匹配失败。
3.3 reg属性:寄存器资源映射
reg 属性描述SPI控制器的寄存器物理基地址和映射长度。内核在驱动探测阶段通过 platform_get_resource() 获取该信息,并调用 ioremap() 完成虚拟地址映射。
属性格式由父节点的 #address-cells 和 #size-cells 决定。对于ARM平台,通常为:
reg = <0x0208c000 0x4000>;
其中 0x0208c000 为寄存器基址,0x4000 为映射长度(16KB)。
| 平台 | #address-cells | #size-cells | reg示例 |
|---|---|---|---|
| ARM 32位 | 1 | 1 | <0x0208c000 0x4000> |
| ARM 64位 | 2 | 2 | <0x00 0x0208c000 0x00 0x4000> |
| RISC-V | 2 | 2 | <0x00 0x10040000 0x00 0x1000> |
3.4 interrupts属性:中断资源描述
interrupts 属性向内核传递SPI控制器的中断号与触发类型。内核通过 platform_get_irq() 获取中断号,并在驱动初始化时调用 request_irq() 注册中断处理函数。
属性值格式依赖于中断控制器父节点定义的 #interrupt-cells:
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
其中:
- GIC_SPI:共享外设中断类型(值为0),区别于PPI私有外设中断
- 38:中断号,与数据手册中的SPI中断编号一致
- IRQ_TYPE_LEVEL_HIGH:高电平触发,SPI控制器通常使用电平触发
| 中断触发类型宏 | 数值 | 适用场景 |
|---|---|---|
IRQ_TYPE_LEVEL_HIGH |
4 | SPI控制器标准中断(推荐) |
IRQ_TYPE_LEVEL_LOW |
8 | 低电平有效的中断控制器 |
IRQ_TYPE_EDGE_RISING |
1 | 边沿触发,较少用于SPI |
IRQ_TYPE_EDGE_FALLING |
2 | 边沿触发,较少用于SPI |
3.5 完整SPI控制器节点示例
以下是一个基于i.MX6UL平台的完整ECSPI控制器节点,整合了上述所有核心属性:
ecspi1: spi@0208c000 {
compatible = "fsl,imx6ul-ecspi", "fsl,imx6q-ecspi";
reg = <0x0208c000 0x4000>;
interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_ECSPI1>,
<&clks IMX6UL_CLK_ECSPI1>;
clock-names = "ipg", "per";
dmas = <&sdma 3 7 1>, <&sdma 4 7 2>;
dma-names = "rx", "tx";
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
/* 从设备子节点在此处添加 */
};
3.6 属性与内核数据结构的映射关系
设备树解析完成后,上述属性被内核映射为 struct spi_controller 的关键字段: