3. I2C设备树绑定:通用I2C设备树节点结构、compatible属性、reg属性、地址配置
好,我们进入I2C设备树绑定的核心部分。说实话,I2C的设备树配置比GPIO要复杂一些,但只要你理解了它的骨架,剩下的就是填参数了。我个人习惯把I2C节点看作「挂在总线上的小设备」,每个设备都有自己的地址、驱动匹配名,以及一些私有配置。
3.1 通用I2C设备树节点结构
先看一个典型的I2C设备节点长什么样。嗯,这里我拿一个温度传感器来举例:
&i2c1 {
status = "okay";
clock-frequency = <100000>;
temperature-sensor@48 {
compatible = "ti,tmp102";
reg = <0x48>;
#address-cells = <1>;
#size-cells = <0>;
};
};
你注意看,整个结构分两层:
- 父节点:I2C控制器本身(比如
i2c1),配置总线频率、状态等 - 子节点:挂在总线上的具体设备,每个设备一个节点
我在项目中遇到过有人把子节点的属性写到父节点里,结果驱动死活不认设备。说白了,父节点管总线,子节点管设备,各司其职。
3.2 compatible属性——驱动匹配的关键
compatible 属性是设备树里最重要的属性之一。它的格式是 "厂商,型号",比如 "ti,tmp102"。内核驱动通过这个字符串来找到对应的驱动程序。
这里有个细节:compatible 可以写多个值,内核会按顺序匹配。比如:
compatible = "ti,tmp102", "nxp,lm75";
内核先尝试匹配 ti,tmp102,如果找不到驱动,再试 nxp,lm75。我曾经在一个项目里用这个技巧兼容了两款引脚兼容的传感器,省去了改板的麻烦。
of_match_table 完全一致,大小写、连字符都不能错。我见过有人把 "tmp102" 写成 "TMP102",结果驱动加载失败,查了半天才发现是大小写问题。
3.3 reg属性——I2C地址配置
reg 属性指定了设备的I2C从机地址。对于7位地址的I2C设备,写法很简单:
reg = <0x48>;
但这里有个坑——地址到底是7位还是10位?设备树里默认是7位地址,范围是0x03到0x77。如果你要用10位地址,需要额外配置 reg 的格式。
为什么地址范围从0x03开始?因为0x00到0x02是保留地址,用于特殊用途。我刚开始做I2C时,选了个0x00的地址,结果总线直接罢工,后来查手册才知道踩了雷区。
3.4 地址配置的注意事项
地址配置看似简单,但有几个地方容易翻车:
- 地址冲突:同一总线上不能有两个设备用同一个地址。我遇到过客户把两个相同型号的传感器焊在同一总线上,结果地址冲突,数据全乱套了。
- 地址偏移:有些芯片的地址是7位,但数据手册里写的是8位(左移了一位)。比如手册写0x90,实际设备树里要填0x48。嗯,这个坑我踩过两次,后来学乖了,每次都要确认是7位还是8位表示。
- 地址位数:如果设备支持10位地址,需要在父节点里声明
#address-cells = <2>,然后子节点的reg写成reg = <0x0 0x48>。
3.5 其他常用属性
除了 compatible 和 reg,I2C设备节点还经常用到这些属性:
| 属性名 | 说明 | 示例 |
|---|---|---|
status |
设备状态,常用 "okay" 或 "disabled" | status = "okay"; |
interrupt-parent |
中断控制器引用 | interrupt-parent = &gpio1; |
interrupts |
中断号和触发方式 | interrupts = <5 IRQ_TYPE_EDGE_FALLING>; |
clock-frequency |
I2C总线频率(父节点配置) | clock-frequency = <400000>; |
你想想看,一个完整的I2C设备节点,其实就是把这些属性组合起来。比如带中断的触摸屏:
&i2c2 {
status = "okay";
clock-frequency = <400000>;
touchscreen@38 {
compatible = "goodix,gt911";
reg = <0x38>;
interrupt-parent = <&gpio3>;
interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio3 19 GPIO_ACTIVE_LOW>;
irq-gpios = <&gpio3 18 GPIO_ACTIVE_HIGH>;
};
};
这里我加了 reset-gpios 和 irq-gpios,这是触摸屏驱动自己定义的私有属性。设备树的灵活性就在这里——你可以为特定设备添加任意属性,只要驱动能解析就行。
3.6 总结一下
I2C设备树绑定的核心就三点:
- 节点结构:父节点管总线,子节点管设备
- compatible:驱动匹配的钥匙,格式要严格
- reg:设备地址,注意7位和8位的区别
说白了,I2C设备树配置就是个填空题。你把总线参数填好,把设备地址填对,把驱动名写准,剩下的就是调试了。我个人经验是,第一次调I2C设备树时,先用 i2cdetect 工具扫一下总线,确认设备确实在预期的地址上响应,然后再去折腾驱动。这样能省掉一半的排查时间。