如何在设备树覆盖片段中强制指定驱动探测顺序?
我正在为搭载Ilitek 9806e显示控制器和Goodix Gt911触控控制器的显示屏编写设备树覆盖(dto)。两者共用一条复位线,初始化时只需触发一次复位。由于Goodix控制器的I2C地址是在复位阶段根据辅助GPIO引脚状态确定的,所以希望仅使用Goodix驱动的复位逻辑,跳过Ilitek驱动的复位操作。
这要求Ilitek的.probe函数必须在Goodix的探测序列完成后再调用。目前尚未找到实现方法,理想方案是通过设备树覆盖而非修改驱动来完成。
我尝试过在面板设备中添加对Goodix设备的引用(比如parent = <>911>),但没有效果。也考虑过为Ilitek驱动添加探测延迟机制,但不清楚如何查询Goodix驱动是否已完成探测序列。
参考的dts文件如下:
// SPDX-License-Identifier: GPL-2.0 /dts-v1/; /plugin/; #include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/gpio/gpio.h> / { compatible = "brcm,bcm2835"; i2c_frag: fragment@0 { target = <&i2c_csi_dsi>; __overlay__ { #address-cells = <1>; #size-cells = <0>; status = "okay"; gt911: gt911@5d { compatible = "goodix,gt911"; reg = <0x5d>; touchscreen-x-mm = <90>; touchscreen-y-mm = <151>; reset-gpios = <&gpio 5 GPIO_ACTIVE_LOW>; irq-gpios = <&gpio 6 0>; interrupt-parent = <&gpio>; interrupts = <6 IRQ_TYPE_EDGE_FALLING>; touchscreen-swapped-x-y=<1>; touchscreen-inverted-y=<1>; }; }; }; dsi_frag: fragment@1 { target = <&dsi1>; __overlay__ { #address-cells = <1>; #size-cells = <0>; status = "okay"; port { dsi_out: endpoint { remote-endpoint = <&dsi_panel_in>; }; }; panel_disp: panel_disp@0 { reg = <0>; compatible = "densitron,dmt050wvnmcmi-1a"; // No reset-gpios specified, reset is performed by i2c_frag // Ensure touchscreen is probed first to perform reset (doesn't work) parent = <>911>; port { dsi_panel_in: endpoint { remote-endpoint = <&dsi_out>; }; }; }; }; }; };
方法一:利用设备树depends-on属性(推荐,Linux 5.15+支持)
内核5.15及以上版本支持设备树的depends-on属性,可以直接指定Ilitek面板设备依赖Goodix触控设备,内核会自动保证先完成Goodix的探测流程,再调用Ilitek的.probe函数。
修改面板节点,新增depends-on属性:
panel_disp: panel_disp@0 { reg = <0>; compatible = "densitron,dmt050wvnmcmi-1a"; depends-on = <>911>; // 明确依赖Goodix设备 port { dsi_panel_in: endpoint { remote-endpoint = <&dsi_out>; }; }; };
同时确保Ilitek节点不配置reset-gpios,让Goodix驱动单独处理复位。
方法二:GPIO Hogging固定复位电平(兼容旧内核)
如果你的内核版本不支持depends-on,可以通过GPIO hogging先把复位线固定到默认状态,再由Goodix驱动完成复位操作,Ilitek驱动不配置复位引脚即可:
在设备树根节点添加GPIO hog节点:
gpio-hog { compatible = "gpio-hog"; reset-gpio = <&gpio 5 GPIO_ACTIVE_LOW>; gpio-line-names = "display-touch-reset"; output-low; // 根据硬件复位电平调整,这里假设低电平复位 status = "okay"; };
这样系统启动时会先把复位线拉到指定状态,Goodix驱动触发复位后,Ilitek驱动因为没有配置复位引脚,不会重复操作。
方法三:用户空间延迟加载驱动(临时 workaround)
如果以上设备树方案都无法生效,可以在系统启动脚本中延迟加载Ilitek驱动,等待Goodix驱动加载完成:
在/etc/rc.local或自定义启动脚本中添加:
# 等待Goodix驱动加载完成 while ! lsmod | grep -q goodix; do sleep 1 done # 加载Ilitek面板驱动 modprobe ilitek_panel_driver
注意替换ilitek_panel_driver为实际的Ilitek驱动模块名。
内容的提问来源于stack exchange,提问作者sAm_vdP

