4. SPI设备树绑定:设备树节点语法、compatible属性、reg属性、spi-max-frequency等关键属性

在嵌入式Linux系统中,设备树(Device Tree)是描述硬件拓扑结构的核心机制。对于SPI设备驱动而言,设备树节点是驱动与硬件之间的“契约”——驱动通过解析设备树节点获取SPI从设备的地址、最大频率、工作模式等关键参数。本章将深入剖析SPI设备树绑定的语法规则与关键属性。

核心概念:设备树节点中的SPI子节点必须遵循特定的绑定规范,否则驱动无法正确识别和配置SPI从设备。错误的绑定可能导致设备无法枚举、数据传输失败甚至系统崩溃。

4.1 SPI设备树节点语法

SPI控制器节点下的每个子节点代表一个挂载在该SPI总线上的从设备。其基本语法结构如下:

spi_controller: spi@xxxxxxx {
    compatible = "vendor,spi-controller";
    reg = <0x...>;
    #address-cells = <1>;
    #size-cells = <0>;
    /* SPI控制器属性 */

    spi_device0: device@0 {
        compatible = "vendor,spi-device";
        reg = <0>;               /* 片选编号,必须 */
        spi-max-frequency = <1000000>; /* 最大SPI时钟频率,必须 */
        /* 可选属性:spi-cpha, spi-cpol, spi-cs-high 等 */
    };

    spi_device1: device@1 {
        compatible = "vendor,another-device";
        reg = <1>;
        spi-max-frequency = <5000000>;
        spi-cpha;                /* 相位模式1 */
        spi-cpol;                /* 极性模式1 */
    };
};
语法要点:
  • 节点命名:子节点名称通常为 device@片选编号,如 adc@0、sensor@1。
  • #address-cells = <1>; #size-cells = <0>;:表示子节点的 reg 属性只包含一个地址(片选号),没有长度字段。
  • 子节点顺序:设备树中的子节点顺序不影响实际片选优先级,片选由 reg 属性值决定。
SPI设备树节点层级结构 SPI 控制器节点 spi_device0: device@0 compatible = "vendor,spi-device" reg = <0> spi-max-frequency = <1000000> spi_device1: device@1 compatible = "vendor,another-device" reg = <1> spi-max-frequency = <5000000> 每个子节点对应一个SPI从设备 reg 属性值决定硬件片选信号

4.2 compatible属性:驱动匹配的关键

compatible 属性是设备树节点与驱动进行匹配的“身份证”。SPI驱动通过该属性值在设备树中查找对应的设备节点,并建立绑定关系。

属性格式 示例 说明
"厂商,设备型号" "ti,ads1256" 标准格式,厂商前缀+设备型号,驱动优先匹配此值
"通用设备类型" "spidev" 通用兼容性标识,用于用户空间SPI设备驱动
多值列表 "ti,ads1256", "generic-adc" 按优先级从高到低列出兼容设备,驱动依次尝试匹配
常见错误:compatible 属性值必须与驱动中 of_match_table 定义的字符串完全一致(包括大小写和标点)。例如,驱动中写 "ti,ads1256",设备树中写 "ti,ADS1256" 将导致匹配失败。

驱动端匹配代码示例:

static const struct of_device_id spi_device_of_match[] = {
    { .compatible = "ti,ads1256", .data = &ads1256_config },
    { .compatible = "maxim,max31865", .data = &max31865_config },
    { /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spi_device_of_match);

static int spi_device_probe(struct spi_device *spi)
{
    const struct of_device_id *match;
    match = of_match_device(spi_device_of_match, &spi->dev);
    if (match) {
        /* 根据 match->data 进行设备初始化 */
    }
    return 0;
}

4.3 reg属性:片选地址与总线位置

reg 属性在SPI子节点中用于指定从设备在SPI总线上的片选编号。该编号直接对应硬件上SPI控制器输出的片选信号(CSn)。

  • 单片选设备:reg = <0>; —— 使用片选信号 CS0。
  • 多片选设备:某些SPI控制器支持多个片选,如 reg = <2>; 表示使用 CS2。
  • 地址单元:由父节点的 #address-cells 决定,通常为1(一个32位整数表示片选号)。
  • 大小单元:由父节点的 #size-cells 决定,通常为0(无长度字段)。
注意事项:
  • 同一SPI控制器下的子节点,reg 值不能重复,否则会导致设备注册冲突。
  • 某些SPI控制器支持“多片选”模式,此时 reg 可能包含多个地址,需参考具体控制器的绑定文档。
  • 如果硬件上片选信号是低电平有效,设备树中通常不需要额外配置,由SPI控制器硬件自动处理。
SPI片选与reg属性映射 SPI 控制器 CS0, CS1, CS2 SCLK, MOSI, MISO 从设备0 reg = <0> → CS0 从设备1 reg = <1> → CS1 从设备2 reg = <2> → CS2 reg 属性值直接映射到硬件片选信号

4.4 spi-max-frequency属性:时钟频率上限

spi-max-frequency 属性定义了SPI从设备所能支持的最大时钟频率(单位:Hz)。SPI控制器在初始化时会根据此属性设置SCLK频率,确保不超过从设备的额定值。

属性值 实际频率 适用场景
<1000000> 1 MHz 低速传感器、ADC、温度芯片
<5000000> 5 MHz 中速数据转换器、存储器
<20000000> 20 MHz 高速ADC、DAC、FPGA配置
<50000000> 50 MHz 高速存储器、显示控制器
驱动行为:SPI核心框架在 spi_setup() 函数中读取 spi-max-frequency,并将其赋值给 spi_device->max_speed_hz。驱动在后续数据传输中应确保实际使用的频率不超过此值。

驱动中读取频率的典型代码:

static int spi_device_probe(struct spi_device *spi)
{
    u32 max_freq;

    /* 设备树解析时已自动设置 spi->max_speed_hz */
    dev_info(&spi->dev, "SPI device max frequency: %u Hz\n", spi->max_speed_hz);

    /* 驱动可以进一步限制频率 */
    if (spi->max_speed_hz > 5000000) {
        dev_warn(&spi->dev, "Limiting frequency to 5 MHz\n");
        spi->max_speed_hz = 5000000;
    }

    return 0;
}

4.5 SPI模式属性:cpha、cpol与cs-high

除了频率,SPI设备还需要配置时钟极性(CPOL)和时钟相位(CPHA),以及片选信号的有效电平。这些属性在设备树中以布尔标志或整数值的形式存在。

设备树属性 对应SPI模式位 说明
spi-cpha SPI_CPHA 时钟相位:1表示数据在第二个时钟边沿采样,0表示第一个边沿
spi-cpol SPI_CPOL 时钟极性:1表示空闲时时钟为高电平,0表示空闲时为低电平
spi-cs-high SPI_CS_HIGH 片选信号高电平有效(默认低电平有效)
spi-3wire SPI_3WIRE 三线模式:MISO和MOSI共用一条数据线
spi-lsb-first SPI_LSB_FIRST LSB优先传输(默认MSB优先)

SPI模式组合与设备树配置示例:

/* SPI模式0:CPOL=0, CPHA=0 */
device@0 {
    compatible = "vendor,device-mode0";
    reg = <0>;
    spi-max-frequency = <1000000>;
    /* 不设置 spi-cpol 和 spi-cpha,默认模式0 */
};

/* SPI模式3:CPOL=1, CPHA=1 */
device@1 {
    compatible = "vendor,device-mode3";
    reg = <1>;
    spi-max-frequency = <5000000>;
    spi-cpol;
    spi-cpha;
};

/* 片选高电平有效 */
device@2 {
    compatible = "vendor,device-cs-high";
    reg = <2>;
    spi-max-frequency = <2000000>;
    spi-cs-high;
};
注意:如果设备树中同时设置了 spi-cpol 和 spi-cpha,驱动将组合成对应的SPI模式(0/1/2/3)。如果从设备数据手册要求特定模式,务必在设备树中正确配置,否则可能导致通信失败。

4.6 完整SPI设备树绑定示例

以下是一个完整的SPI设备树绑定示例,包含多个从设备及其关键属性:

&spi1 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&spi1_pins>;

    /* 温度传感器:MAX31865 */
    temp_sensor: max31865@0 {
        compatible = "maxim,max31865";
        reg = <0>;
        spi-max-frequency = <5000000>;
        spi-cpha;
        spi-cpol;
        /* 可选:中断引脚 */
        interrupts = <&gpio3 15 IRQ_TYPE_EDGE_FALLING>;
    };

    /* ADC:ADS1256 */
    adc: ads1256@1 {
        compatible = "ti,ads1256";
        reg = <1>;
        spi-max-frequency = <19200000>;
        spi-cpol;
        /* 参考电压配置 */
        vref-supply = <&vref_2_5v>;
    };

    /* 用户空间SPI设备(spidev) */
    spidev@2 {
        compatible = "spidev";
        reg = <2>;
        spi-max-frequency = <10000000>;
    };
};
关键点总结:
  • compatible:驱动匹配的唯一标识,必须与驱动中的 of_match_table 一致。
  • reg:片选编号,决定硬件CS信号,同一控制器下不能重复。
  • spi-max-frequency:从设备最大时钟频率,驱动应遵守此上限。
  • spi-cpol/spi-cpha:定义SPI模式,必须与从设备数据手册一致。
  • spi-cs-high:片选极性,默认低电平有效,特殊设备需配置。
SPI设备树绑定完整流程 设备树节点 compatible, reg spi-max-frequency, 模式 SPI核心框架 of_spi_parse_dt() 创建 spi_device SPI驱动 probe() 调用 设备初始化 设备树 → SPI核心 → 驱动:完整的绑定链路 每个环节的属性解析都依赖于正确的设备树绑定语法 设备树属性与驱动字段映射 设备树属性 驱动字段 说明 compatible of_match_table 驱动匹配标识 reg spi->chip_select 硬件片选编号 spi-max-frequency spi->max_speed_hz 最大时钟频率

4.7 常见绑定错误与调试方法

在实际开发中,SPI设备树绑定错误是导致驱动无法正常工作的常见原因。以下列出典型错误及其排查方法:

错误现象 可能原因 排查方法
驱动 probe 未调用 compatible 不匹配 检查 /sys/firmware/devicetree/base/.../compatible 内容
SPI设备未注册 reg 值冲突或超出范围 查看内核日志 dmesg | grep spi
数据传输错误 spi-max-frequency 过高或模式错误 使用逻辑分析仪抓取SPI波形
片选信号异常 spi-cs-high 配置错误 检查设备树中片选极性设置
设备树编译错误 语法错误或缺少必要属性 使用 dtc -I dts -O dtb 编译检查
调试技巧:在 /sys/kernel/debug/spi/ 目录下可以查看已注册的SPI设备信息,包括片选、频率、模式等。使用 cat /sys/kernel/debug/spi/spiX/spiX.Y 查看具体设备参数。

通过本章的学习,你应该能够熟练编写SPI设备树节点,正确配置compatible、reg、spi-max-frequency等关键属性,并理解这些属性如何影响驱动的匹配与初始化过程。掌握设备树绑定是SPI驱动开发的基础,也是后续实现高效数据传输的前提。