21、TSP设备树配置:compatible属性、reg属性、interrupts属性、pinctrl配置

各位同学,今天我们来聊聊触摸屏驱动里最基础、也最关键的一环——设备树配置。说实话,我刚入行那会儿,觉得设备树就是一堆枯燥的键值对,后来踩了几个坑才明白,这玩意儿写不对,驱动根本跑不起来。

设备树说白了就是硬件的“身份证”。内核通过它来识别你的触摸屏是什么型号、接在哪个总线上、用哪个中断引脚、GPIO怎么配。今天我就带大家把这几个核心属性掰开揉碎了讲清楚。

核心要点:设备树配置是驱动与硬件之间的桥梁。compatible负责“认人”,reg负责“找地址”,interrupts负责“传信号”,pinctrl负责“管引脚”。四者缺一不可。

一、compatible属性:驱动与硬件的“接头暗号”

compatible属性,我习惯叫它“身份证号”。内核在加载驱动时,会拿这个字符串去匹配驱动列表。匹配上了,驱动就绑定到设备上。

格式很简单:"厂商,型号"。比如:

compatible = "goodix,gt911";

这里要注意,厂商名一般用小写,型号用数字或字母组合。我在项目中遇到过有人把厂商名写成了大写,结果驱动死活加载不上,查了半天才发现是大小写不匹配。嗯,这种低级错误,犯过一次就记住了。

有时候一个芯片可能兼容多个型号,你可以写多个compatible字符串:

compatible = "goodix,gt911", "goodix,gt9xx";

内核会按顺序匹配,匹配到第一个就停。我个人习惯把最精确的型号写在最前面,这样更保险。

二、reg属性:告诉驱动“你在哪”

reg属性描述的是设备在总线上的地址。对于I2C接口的触摸屏,reg就是I2C从设备地址。

&i2c3 {
    status = "okay";
    
    touchscreen@5d {
        compatible = "goodix,gt911";
        reg = <0x5d>;
    };
};

你想想看,I2C总线上可能挂着好几个设备,每个设备都有一个唯一的地址。reg就是告诉驱动:“嘿,我在这儿呢!”

这里有个坑——I2C地址有7位和10位之分。大部分触摸屏用7位地址,但有些芯片支持地址浮动。我记得有一次调试,明明芯片手册上写的是0x5d,但实际读出来是0xba。后来发现是芯片的ADDR引脚电平没拉对,导致地址偏移了一位。所以,reg的值一定要和硬件实际配置一致,不能光看手册。

注意:I2C地址通常是7位,但设备树里写的是8位值(左移1位后的结果)。比如7位地址0x5d,在设备树里写0x5d还是0xba?答案是0x5d。内核会自动处理移位,你直接写芯片手册上的地址就行。

三、interrupts属性:中断信号的“快递单号”

触摸屏是典型的“中断驱动”设备。用户手指一碰,芯片就拉高或拉低中断引脚,通知CPU来读数据。interrupts属性就是描述这个中断信号的。

格式一般是:interrupts = <中断控制器编号 中断号 触发方式>

touchscreen@5d {
    compatible = "goodix,gt911";
    reg = <0x5d>;
    interrupt-parent = <&gpio1>;
    interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
};

这里我解释一下:

  • interrupt-parent:指定中断由哪个GPIO控制器管理。不写的话,默认用父节点的中断控制器。
  • 第一个参数:中断号,对应GPIO的引脚编号。比如GPIO1_13,就是13。
  • 第二个参数:触发方式。常用的有:
宏定义 触发方式 适用场景
IRQ_TYPE_EDGE_RISING 上升沿触发 芯片在事件发生时拉高引脚
IRQ_TYPE_EDGE_FALLING 下降沿触发 芯片在事件发生时拉低引脚(最常见)
IRQ_TYPE_LEVEL_HIGH 高电平触发 持续高电平表示有事件
IRQ_TYPE_LEVEL_LOW 低电平触发 持续低电平表示有事件

我曾经在一个项目里把下降沿写成了上升沿,结果手指按下去没反应,抬起来反而触发中断。你想想看,用户点一下屏幕,数据还没读呢,中断就结束了。这种问题排查起来特别头疼,最后用示波器一看,才发现是触发极性反了。

小技巧:如果不确定中断触发方式,可以先配成双边沿触发(IRQ_TYPE_EDGE_BOTH),然后在中断处理函数里打印引脚电平,用示波器或逻辑分析仪确认实际波形。确认后再改回单边沿,减少不必要的唤醒次数。

四、pinctrl配置:GPIO引脚的“上岗培训”

pinctrl,全称pin control,就是管脚控制。触摸屏的I2C引脚、中断引脚、复位引脚,都需要通过pinctrl配置成正确的功能模式。

设备树里一般这样写:

&i2c3 {
    status = "okay";
    
    touchscreen@5d {
        compatible = "goodix,gt911";
        reg = <0x5d>;
        interrupt-parent = <&gpio1>;
        interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
        pinctrl-names = "default";
        pinctrl-0 = <&ts_int_default &ts_reset_default>;
    };
};

然后在pinctrl节点里定义具体的引脚配置:

&pinctrl {
    ts_int_default: ts_int_default {
        pins = "GPIO1_13";
        function = "gpio";
        bias-pull-up;
        input-enable;
    };
    
    ts_reset_default: ts_reset_default {
        pins = "GPIO1_12";
        function = "gpio";
        output-high;
    };
};

这里我解释一下pinctrl的套路:

  • pinctrl-names:定义状态名称,一般至少有一个"default"状态。驱动可以在不同阶段切换不同状态,比如休眠时切到"sleep"状态来省电。
  • pinctrl-0:引用具体的引脚配置节点。可以引用多个,用空格隔开。
  • 引脚配置节点:里面定义引脚号、功能模式、上下拉、驱动能力等。

我个人习惯把中断引脚配上拉输入,复位引脚配成推挽输出。为什么?因为中断引脚默认高电平,手指按下时拉低,配上拉可以保证空闲时电平稳定。复位引脚需要主动拉低再拉高来复位芯片,所以必须配成输出。

踩坑提醒:我曾经遇到过pinctrl配置了,但引脚功能死活不对。后来发现是pinctrl节点和i2c节点不在同一个.dtsi文件里,编译时pinctrl节点被覆盖了。所以,一定要确认pinctrl节点被正确编译进去了,可以在生成的.dtb文件里反编译检查。

五、完整示例:一个典型的TSP设备树节点

说了这么多,我们来拼一个完整的例子。假设我们用的是Goodix GT911,接在I2C3总线上,中断引脚是GPIO1_13,复位引脚是GPIO1_12:

&i2c3 {
    status = "okay";
    clock-frequency = <400000>;  // I2C时钟400kHz
    
    touchscreen@5d {
        compatible = "goodix,gt911";
        reg = <0x5d>;
        
        interrupt-parent = <&gpio1>;
        interrupts = <13 IRQ_TYPE_EDGE_FALLING>;
        
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&ts_int_default &ts_reset_default>;
        pinctrl-1 = <&ts_int_sleep &ts_reset_sleep>;
        
        reset-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
        irq-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
        
        touchscreen-size-x = <1024>;
        touchscreen-size-y = <600>;
    };
};

注意这里我加了reset-gpiosirq-gpios,这是驱动自己定义的属性,用来获取GPIO句柄。设备树里除了标准属性,驱动开发者也可以自定义属性,只要驱动代码里能解析就行。

六、知识体系梳理

为了让大家更直观地理解这几个属性的关系,我画了一张图:

TSP设备树核心属性关系图 触摸屏设备节点 compatible 驱动匹配标识 reg I2C/SPI设备地址 interrupts 中断信号配置 pinctrl 引脚功能配置 配置要点 • compatible:格式"厂商,型号",精确匹配 • reg:与硬件实际地址一致,注意I2C地址格式 • interrupts:确认触发方式,用示波器验证波形 • pinctrl:配置上下拉和输入输出方向,避免引脚浮空

从这张图可以看出来,设备树节点就像一棵树的树干,四个属性是主要的枝干,各自负责不同的功能。驱动加载时,先通过compatible找到对应的驱动,然后通过reg访问硬件,通过interrupts注册中断,通过pinctrl配置引脚。四者配合,触摸屏才能正常工作。

七、写在最后

设备树配置这东西,说难不难,说简单也不简单。我见过太多人把compatible写错、把中断号搞混、把pinctrl漏掉。其实只要记住一句话:设备树是写给内核看的硬件说明书,每个属性都要和实际硬件一一对应

嗯,今天的内容就到这里。配置设备树的时候,多对照芯片手册和原理图,多检查几遍,能省去后面很多调试时间。


公众号:蓝海资料掘金营,微信deep3321