3. 设备树中SPI节点的描述

在嵌入式Linux系统中,SPI外设的硬件拓扑与驱动绑定完全通过设备树(Device Tree)描述。设备树节点分为两层:SPI控制器节点(定义主机端SPI总线能力)和SPI从设备子节点(定义挂载在总线上的具体外设)。正确配置这两层节点的属性,是SPI驱动正常工作的前提。

核心原则:SPI控制器节点提供总线控制器的硬件资源(寄存器基址、中断、时钟、DMA等);SPI从设备子节点描述外设的片选、通信速率、模式及与驱动的绑定关系。两者通过父子层级结构关联。

3.1 SPI控制器节点属性

SPI控制器节点通常位于SoC的soc或amba总线节点下,其compatible属性匹配对应的SPI主机驱动。以下为典型控制器节点属性清单:

属性名 类型 说明 示例值
compatible string 匹配SPI主机驱动,格式"厂商,型号" "rockchip,rk3399-spi"
reg u32/u64对 控制器寄存器基址与长度 <0xff1c0000 0x1000>
interrupts u32 SPI控制器中断号
clocks phandle SPI模块时钟与PCLK时钟 <&cru SCLK_SPI0>, <&cru PCLK_SPI0>
clock-names string-list 时钟名称,与clocks对应 "spi", "apb_pclk"
dmas phandle DMA通道(可选) <&dmac 0>, <&dmac 1>
dma-names string-list DMA通道名称 "tx", "rx"
#address-cells u32 子节点地址单元数,固定为1 <1>
#size-cells u32 子节点大小单元数,固定为0 <0>
提示:#address-cells = <1> 和 #size-cells = <0> 是SPI控制器的固定约定。子节点的reg属性仅表示片选编号(CS index),而非地址范围。

以下为完整的SPI控制器节点示例(以Rockchip RK3399为例):

spi0: spi@ff1c0000 {
    compatible = "rockchip,rk3399-spi";
    reg = <0xff1c0000 0x1000>;
    interrupts = ;
    clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
    clock-names = "spi", "apb_pclk";
    dmas = <&dmac 0>, <&dmac 1>;
    dma-names = "tx", "rx";
    #address-cells = <1>;
    #size-cells = <0>;
    status = "disabled";
    /* 子节点在此处添加 */
};
SPI控制器节点属性结构 SPI控制器节点 spi@ff1c0000 compatible = "rockchip,rk3399-spi" reg = <0xff1c0000 0x1000> interrupts = <GIC_SPI 48> clocks = <&cru SCLK_SPI0> #address-cells = <1> #size-cells = <0> SPI从设备子节点 spi-device@0 reg = <0> (CS0) compatible = "vendor,device" spi-max-frequency = <10000000> spi-cpha; spi-cpol; spi-device@1 reg = <1> (CS1) compatible = "vendor,device2" spi-max-frequency = <5000000> spi-3wire;

3.2 SPI从设备子节点属性

每个挂载在SPI总线上的外设,在控制器节点内以一个子节点表示。子节点的reg属性指定片选编号,compatible属性匹配具体设备驱动。以下为关键属性详解:

3.2.1 reg属性——片选编号

reg在SPI子节点中表示片选线索引(CS index),从0开始。控制器根据该值驱动对应的GPIO或硬件片选信号。一个控制器最多支持多个片选,具体数量由硬件决定。

/* 片选0上的温度传感器 */
temp_sensor: sensor@0 {
    reg = <0>;          /* CS0 */
    compatible = "ti,lm70";
    spi-max-frequency = <5000000>;
};

/* 片选1上的ADC */
adc_device: adc@1 {
    reg = <1>;          /* CS1 */
    compatible = "ti,ads7950";
    spi-max-frequency = <10000000>;
};

3.2.2 compatible属性——驱动匹配

格式为"厂商,型号",内核SPI设备驱动通过of_match_table匹配该字符串。支持多级兼容(如"ti,lm70", "ti,lm71"),驱动优先匹配第一个。

3.2.3 spi-max-frequency属性——最大通信速率

指定该从设备支持的最大SPI时钟频率(单位Hz)。控制器驱动在初始化时会根据该值配置SCLK分频系数。实际通信速率不得超过该值,否则可能导致数据错误。

常见错误:spi-max-frequency设置过高(超过从设备规格)会导致通信不稳定;设置过低则浪费总线带宽。建议参考从设备数据手册的SCLK上限,并保留20%余量。

3.2.4 SPI模式属性

通过以下布尔属性配置SPI模式(CPOL/CPHA组合):

属性 作用 对应模式
spi-cpol 时钟极性:空闲时SCLK为高电平 模式1/3(CPOL=1)
spi-cpha 时钟相位:数据在第二个边沿采样 模式2/3(CPHA=1)
spi-3wire 三线模式(无MISO/MOSI区分) 半双工模式
spi-cs-high 片选信号高电平有效(默认低有效) 片选极性反转
spi-lsb-first LSB先传输(默认MSB先) 位序反转

模式组合示例:

/* SPI模式3:CPOL=1, CPHA=1 */
flash@0 {
    reg = <0>;
    compatible = "jedec,spi-nor";
    spi-max-frequency = <80000000>;
    spi-cpol;      /* 空闲高电平 */
    spi-cpha;      /* 第二个边沿采样 */
};
SPI模式配置与波形对应关系 模式0 CPOL=0, CPHA=0 空闲低电平 第一个边沿采样 模式1 CPOL=0, CPHA=1 空闲低电平 第二个边沿采样 模式2 CPOL=1, CPHA=0 空闲高电平 第一个边沿采样 模式3 CPOL=1, CPHA=1 空闲高电平 第二个边沿采样 设备树属性与模式映射 • 无属性 → 模式0(默认) • spi-cpha → 模式1(CPHA=1) • spi-cpol → 模式2(CPOL=1) • spi-cpol + spi-cpha → 模式3

3.3 完整设备树节点示例

以下展示一个包含两个从设备的完整SPI控制器节点:

&spi0 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&spi0_clk &spi0_csn0 &spi0_mosi &spi0_miso>;

    /* 从设备1:SPI NOR Flash */
    flash@0 {
        reg = <0>;
        compatible = "jedec,spi-nor";
        spi-max-frequency = <50000000>;
        spi-cpol;
        spi-cpha;
        m25p,fast-read;
        partitions {
            compatible = "fixed-partitions";
            #address-cells = <1>;
            #size-cells = <1>;
            partition@0 {
                label = "bootloader";
                reg = <0x0 0x100000>;
            };
            partition@100000 {
                label = "kernel";
                reg = <0x100000 0x300000>;
            };
        };
    };

    /* 从设备2:SPI温度传感器 */
    temp@1 {
        reg = <1>;
        compatible = "ti,lm70";
        spi-max-frequency = <5000000>;
        spi-3wire;          /* 三线模式 */
    };
};
关键检查点:
  • 控制器节点status = "okay"确保使能;
  • 子节点reg值必须与硬件片选GPIO对应;
  • spi-max-frequency不能超过控制器最大支持频率和从设备规格的较小值;
  • SPI模式属性(cpol/cpha)必须与从设备数据手册一致,否则通信失败。

3.4 常见配置错误与排查

错误现象 可能原因 排查方法
驱动probe不调用 compatible不匹配或status="disabled" 检查/sys/firmware/devicetree/下节点内容
SPI通信数据全0xFF 片选未选中或模式不匹配 用示波器测量CS/SCLK/MOSI波形
通信速率异常 spi-max-frequency超出硬件能力 降低频率测试,检查时钟树配置
多个设备冲突 reg值重复或片选GPIO冲突 确保每个子节点reg唯一
调试技巧:使用dtc -I dtb -O dts反编译设备树二进制,确认节点属性是否被正确编译。运行时查看/proc/device-tree/下的属性值,验证内核解析结果。