Linux驱动开发:SPI设备树处理过程

发布于:2025-04-12 ⋅ 阅读:(19) ⋅ 点赞:(0)

目录

一、SPI设备树文件 

1、spi_master设备节点

2、spi_master扩展配置 

3、spi_device设备节点 

二、SPI设备树处理过程

1、platform_driver

2、platform_device_id

3、spi_imx_probe

spi_alloc_master

spi_bitbang_start 

spi_register_master 

of_spi_register_master

of_register_spi_devices

总结

1. 通过平台总线模型匹配 SPI 控制器设备和对应的驱动

2. 匹配到驱动后通过 probe 函数进行 spi_master 的注册 

3. SPI 子设备也是通过 spi_master 进行解析和注册


SPI控制器一般工作在主模式,接有多个SPI子设备。

一、SPI设备树文件 

1、spi_master设备节点

设备树也会有一个节点对应spi_master,spi_master里也会有多个节点,对应多个spi_device。

一个典型的spi_master设备树节点如下所示:

ecspi1: ecspi@02008000 {
					#address-cells = <1>;
					#size-cells = <0>;
					compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";
					reg = <0x02008000 0x4000>;
					interrupts = <GIC_SPI 31 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";
					status = "disabled";
				};

ecspi1即为设备节点的标签,用于在设备树的其他地方引用此节点。

ecspi@02008000是设备节点的名称,ecspi代表设备类型,02008000该设备的基地址。

后面有三个关键的属性信息:

  • #address-cells = <1>;代表设定子节点地址信息所占用的 32 位单元数量,这里为 1 个单元。
  • #size-cells = <0>;代表设定子节点大小信息所占用的 32 位单元数量,这里为 0 个单元,意味着子节点不提供大小信息。
  • compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";属性给出了一系列字符串,用于表明该设备与哪些驱动程序兼容。通过这个属性来找到对应的驱动程序。

2、spi_master扩展配置 

在其他的设备树文件通过引用这个spi_master来进行更详细的设备树编写,如下所示:

&ecspi1 {
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_ecspi1>;
    
    fsl,spi-num-chipselects = <2>;
    cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>, <&gpio4 24 GPIO_ACTIVE_LOW>;
    status = "okay";

    dac: dac {
        compatible = "spidev";
        reg = <0>;
        spi-max-frequency = <20000000>;
    };
    
};

 这段代码是设备树中对之前定义的ecspi1节点进行的扩展配置,为其添加了引脚控制、片选信号、设备状态等信息,同时还定义了SPI从设备。

  • fsl,spi-num-chipselects表明该 SPI 控制器支持的片选信号数量为 2 个。
  • cs-gpios定义了这两个片选信号对应的 GPIO 引脚。&gpio4 是对 GPIO 控制器 4 的引用,26 和 24 分别是 GPIO 引脚编号,GPIO_ACTIVE_LOW 表示片选信号为低电平有效。

3、spi_device设备节点 

上述的扩展配置还定义了一个子设备节点。 

dac: dac {
    compatible = "spidev";
    reg = <0>;
    spi-max-frequency = <20000000>;
};
  • compatible 指定该设备与 "spidev" 驱动兼容
  • reg 表示示该设备在 SPI 总线上的片选编号为 0。
  • spi-max-frequency 设定该设备支持的最大 SPI 通信频率为 20 MHz。

上述的三个书写时spi子设备节点的必要属性,如需要更详细的配置,也需要在设备树文件中详细的提供,如:通过配置spi_cpol来配置极性。

二、SPI设备树处理过程

在介绍SPI设备树处理过程之前, 我们先来看看SPI设备相关的结构体。我们以上述设备树文件的spi_master设备节点对应的驱动程序为例。

1、platform_driver

platform_driver类型的结构体如下

 

platform_driver结构体里的.id_table注册的是spi_imx_devtype结构体数组,它是一个platform_device_id类型的结构体数组。

2、platform_device_id

platform_device_id结构体数组主要用于平台设备驱动,在驱动注册时可以指定这个数组,内核会依据设备名称来匹配相应的驱动。 

可以看到,这个结构体数组的最后一个元素的.name为"imx6il-ecspi"。

当内核发现名称匹配的平台设备时,就会调用spi_imx_probe函数。

3、spi_imx_probe

当平台的设备和驱动匹配后,会调用.probe函数。

spi_imx_probe函数的主要实现有以下几点

spi_alloc_master

这个probe函数会去分配一个 spi_master。

spi_bitbang_start 

此函数用于启动SPI通信 

通过spi_bitbang_start去注册spi_master。

 

spi_register_master 

通过spi_register_master去注册master的相关内容。

 

of_spi_register_master

这个函数里的 的of_gpio_named_count函数就可以把设备树文件里的cs-gpios定义的两个片选信号对应的 GPIO 引脚记录下来。

 

of_register_spi_devices

这个函数就会把设备树里的spi_device进行注册。

 

总结

1. 通过平台总线模型匹配 SPI 控制器设备和对应的驱动

在 Linux 内核里,SPI 控制器设备可以借助平台总线模型来实现与对应驱动的匹配。平台总线模型是一种用于连接设备和驱动的抽象机制,它借助设备树(Device Tree)或者传统的设备注册方式来描述设备信息,然后依据 compatible 属性或者设备名称来完成设备和驱动的匹配。

2. 匹配到驱动后通过 probe 函数进行 spi_master 的注册 

当平台总线模型成功匹配到设备和驱动后,会调用驱动的 probe 函数。在 probe 函数中,通常会完成 spi_master 结构体的初始化和注册工作。spi_master 代表着一个 SPI 主机控制器,它负责管理和控制连接到该控制器的所有 SPI 从设备。 

3. SPI 子设备也是通过 spi_master 进行解析和注册

SPI 子设备指的是连接到 SPI 主机控制器上的具体设备,如传感器、存储器等。这些子设备的解析和注册通常是通过spi_master来完成的。在设备树中,SPI 子设备会作为 SPI 控制器节点的子节点来定义。当spi_master注册成功后,内核会依据设备树信息解析出这些子设备,并通过spi_register_device函数将它们注册到系统中。