首先先看SPI的整体应用-内核-硬件的框架在硬件层我们可以看到存在SPI控制器和SPI外设而我们一般操作的是外设所以写的驱动也是外设的驱动而SPI控制器连接的是SPI适配器的驱动层这部分驱动是由芯片原厂工程师进行编写的。我们本篇文章描述的是设备树的写法我们知道设备树描述的是硬件设备与CPU无法自动发现的硬件连接关系由图可知对于SPI来说或者说对于我们要编写一个SPI外设来说具有两个硬件设备一个是SPI控制器一个是SPI外设一般情况下SPI控制器的设备树是原厂工程师写好了的所以我们一般只需要自己写SPI外设的设备树即可。GPIOGPIO也是如此分为GPIO控制器和GPIO“外设”即使用GPIO的设备如led我们需要编写的也是GPIO“外设”的设备树。、接下里我们对比两种外设的写法GPIO控制器及其GPIO使用者设备树GPIO控制器gpio1: gpio0209c000 { compatible fsl,imx6ul-gpio; reg 0x0209c000 0x4000; interrupts GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH; gpio-controller; #gpio-cells 2; interrupt-controller; #interrupt-cells 2; };可知这个节点可以作为GPIO控制器也可以作为中断控制器。GPIO“外设”led { compatible mycompany,myled; led-gpios gpio1 3 GPIO_ACTIVE_LOW; };SPI控制器及其外设设备树SPI控制器spi控制器节点一般在芯片级.dtsi文件中如RK3588.dtsiSPI外设spi0 { status okay; // 启用 SPI0 控制器 pinctrl-names default; pinctrl-0 spi0m1_pins; // 确保引脚复用配置正确 /* 你的外设子节点 */ my_sensor0 { compatible vendor,my-sensor-model; // 必须与驱动中的 of_match_table 一致 reg 0; // 使用 CS0 (片选0) spi-max-frequency 10000000; // 最大时钟频率 10MHz /* 可选属性 */ spi-cpol; // 如果外设需要 CPOL1 spi-cpha; // 如果外设需要 CPHA1 /* 中断引脚配置如果外设带中断 */ interrupt-parent gpio1; interrupts RK_PA1 IRQ_TYPE_EDGE_FALLING; }; };注reg属性用来片选spi-max-frequency用来设置时钟频率这两个参数必须要写不然设备无法加载。写法分析我们可以发现GPIO 和 SPI 都有“控制器”和“外设”但它们在设备树里的写法不同根本原因是SPI 是总线外设是挂在 SPI 控制器下面的“子设备”GPIO 不是总线外设只是“使用了某几根 GPIO 线”。设备树既可以用父子节点表示总线拓扑也可以用phandle 引用表示资源连接关系。Linux 设备树文档也说明DT 本质是描述硬件的数据结构除了树形父子关系外还允许节点之间建立任意引用关系常见 binding 会描述 data bus、GPIO connection、interrupt line、peripheral device 等硬件特征。SPI 是典型总线结构SPI 控制器 ├── CS0 外设 ├── CS1 外设 └── CS2 外设而GPIO不是父子结构GPIO 更像是一组“可借用的引脚资源”。对比SPIGPIO本质总线引脚资源外设和控制器关系外设挂在 SPI 控制器下面外设使用 GPIO 控制器的一根线设备树表示父子节点phandle 引用外设身份spi_device通常是 platform device / input device / led device 等地址含义reg CS号gpiox pin flags内核解析SPI core 扫描子节点GPIO consumer API 解析xxx-gpios