2026-06-29 Goodix GT9147 触摸屏 -6 ENXIO:地址写成 0x5d,实测在 0x14
netboot 启动 imx6ull-aes.dtb 时,Goodix 触摸屏驱动 probe 失败,串口日志一片 Error ... -6。这篇记一个反复会踩的坑:Goodix 的 I2C 从地址不是固定的,而 设备树(和很多教程)默认写 0x5d,但本板实测在 0x14。只要换板子、换 INT/RESET 上电时序,地址就可能落到另一个值——所以把排查方法记下来比记答案更值。
Context
- 触摸芯片:正点原子 i.MX6ULL AES 板上的 Goodix GT9147,挂在 i2c-1。
- 驱动:mainline
drivers/input/touchscreen/goodix.c(分析型章节路线,拆现成驱动 不重写,见 触摸章节)。 - 设备树:netboot base 镜像
imx6ull-aes.dtb由linux/imx6ull-aes.dts#include "imx6ull-aes.dtsi"编出,goodix 节点就在这个共享 dtsi 里。
Symptom
内核起来后,触摸驱动连试两次读寄存器都失败,然后放弃 probe:
[ 12.006241] Goodix-TS 1-005d: Error reading 1 bytes from 0x8140: -6
[ 12.035073] Goodix-TS 1-005d: Error reading 1 bytes from 0x8140: -6
[ 12.064510] Goodix-TS 1-005d: I2C communication failure: -6之后 /dev/input/eventX 不出现,触摸不可用。注意:probe 失败不是 fatal, 后面 DHCP、继续启动都正常——别把它和「起不来」混淆。
Key Insight —— -6 是「设备没应答」,先别怪驱动
逐字段拆这一行 Goodix-TS 1-005d: Error reading 1 bytes from 0x8140: -6:
1-005d= Linux i2c bus 1、从地址 0x5d(这是设备树reg给的)。0x8140= Goodix 的 Product ID 寄存器(GT9147_PRODUCT_ID)。驱动 probe 时 第一步就是读它来辨认芯片型号。-6 = -ENXIO= I2C 传输层最经典的「No ACK」:master 在 0x5d 发起读, 总线上没有任何设备在那个地址应答。
所以问题不在驱动、不在中断、不在供电时序——而是驱动去找设备的那个地址上没有设备。 最该先做的一步不是读代码,是扫总线。
Investigation
Step 1 —— i2cdetect 直接看芯片在哪个地址
板子进 shell 后(这个 probe 是内核侧、boot 早期就发生,跟 rootfs/init 无关, 哪怕 NFS root 还没修好也能验):
i2cdetect -y 1
# 0 1 2 3 4 5 6 7 8 9 a b c d e f
# 00: -- -- -- -- -- -- -- -- -- -- -- -- --
# 10: -- -- -- -- 14 -- -- -- -- -- -- -- -- -- -- --
# 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
# ...(其余全 --)整条 i2c-1 上只有 0x14 那一格有应答。同总线的 ov5640@3c 是 status="disabled",所以 0x14 必然就是 GT9147,没有歧义。芯片在 0x14, 驱动却去 0x5d 找 → -6。
Step 2 —— 反编译正在 boot 的 dtb,确认 reg
dtc -I dtb -O dts /home/charliechen/tftp/imx6ull-aes.dtb 2>/dev/null | grep -A3 'gt9147@'
# gt9147@5d {
# compatible = "goodix,gt9147\0goodix,gt9xx";
# reg = <0x5d>;果然 reg = <0x5d>。源在 driver/device_tree/alpha-board/linux/imx6ull-aes.dtsi 的 goodix 节点。
Step 3 —— 为什么是 0x14 不是 0x5d
Goodix GT9xx 系列的 7-bit I2C 从地址不是固定的,由 RESET 上升沿那一刻 INT 引脚的电平决定:
| INT @ RESET 上升沿 | 7-bit 地址 | 8-bit 写/读 |
|---|---|---|
| 高 | 0x5d | 0xBA / 0xBB |
| 低 | 0x14 | 0x28 / 0x29 |
本板的 INT 网络在复位瞬间是低电平 → 芯片落在 0x14。很多教程/NXP EVK 的 dts 默认写 0x5d(INT 上拉的情况),照抄到这块板就对不上。换板子或改 INT/RESET 上拉, 地址就可能变——这正是要写这篇笔记的原因。
Root Cause
设备树 goodix 节点 reg = <0x5d> 与芯片实际地址 0x14 不符 → 驱动在 0x5d 读 Product ID 寄存器(0x8140)得不到 ACK → -ENXIO → probe 失败。
Fix
把 reg 和节点名 @ 后的地址从 0x5d 改成 0x14。netboot base 镜像的源在三处, 要同步改(光改一处会被构建流程覆盖回去):
- patch(构建真正
git apply的,最权威):patches/linux_mainline/linux_mainline-feat-imx6ull_patches-20260616.patch - 镜像副本(人读的工作源):
driver/device_tree/alpha-board/linux/imx6ull-aes.dtsi - 树里已 apply 的副本(重编前必改这个,否则编出的还是旧的):
third_party/linux_mainline/arch/arm/boot/dts/nxp/imx/imx6ull-aes.dtsi
三处都是:
- gt9147: gt9147@5d {
+ gt9147: gt9147@14 {
compatible = "goodix,gt9147", "goodix,gt9xx";
- reg = <0x5d>;
+ reg = <0x14>;节点名
@5d→@14不是内核必需(内核用reg),但 dtc 会因 unit-address 与reg不一致而 warning,顺手改干净。labelgt9147:不变,>9147引用不受影响。
快速重编 dtb(不用整编内核、不用交叉工具链)
cd third_party/linux_mainline
make ARCH=arm imx_aes_mainline_defconfig # 一次性生成 .config
make ARCH=arm nxp/imx/imx6ull-aes.dtb # ⚠ 必须带 nxp/imx/ 子路径坑:mainline 7.1 把 imx 的 dts 挪到了
arch/arm/boot/dts/nxp/imx/子目录, 裸make imx6ull-aes.dtb会报No rule to make target 'arch/arm/boot/dts/imx6ull-aes.dtb'。目标名得带子路径。 编 dtb 只用到 host 的 dtc,不需要CROSS_COMPILE,几十秒完成。
部署 + 验证
# 备份旧 dtb(沿用 -before-*-fix 命名习惯)
cp -n /home/charliechen/tftp/imx6ull-aes.dtb \
/home/charliechen/tftp/imx6ull-aes-before-goodix-fix.dtb
# 拷新的上去
cp arch/arm/boot/dts/nxp/imx/imx6ull-aes.dtb /home/charliechen/tftp/imx6ull-aes.dtb
# 验证 reg 已变
dtc -I dtb -O dts /home/charliechen/tftp/imx6ull-aes.dtb 2>/dev/null | grep -A2 'gt9147@'然后重启板子(netboot 开机才重新 tftp 拉 dtb,各章 dtb 互斥,见 DTB Deploy & Boot 相关约定)。
Operational Rule(真正的 takeaway)
- Goodix 报
-6,第一步永远是i2cdetect -y <bus>,看芯片实际在哪个地址。 别急着翻驱动、查中断、调时序——地址不对一切白搭。 - Goodix 地址由 INT@RESET 决定,0x5d / 0x14(乃至 0x5e / 0x15)都合法。换板、 换上电时序后地址可能变,以
i2cdetect实测为准,别迷信 dts/教程里的值。 - 改 netboot base 镜像的节点,patch + 镜像 + 树里副本三处同步,否则构建回退。
- 改完只编单个 dtb 走
make ARCH=arm nxp/imx/imx6ull-aes.dtb,拷 tftp,重启板子。
Triage One-Liner
Goodix-TS <bus>-<addr>: Error reading ... -6→-6 = ENXIO = 没 ACK。 先i2cdetect -y <bus>看芯片真实地址,再dtc反编译 dtb 对reg。两边对不上 就是地址写错——别查驱动、别查中断。
Command Cheat-Sheet
# 1) 扫总线,看 Goodix 实际在哪个地址(排查首选)
i2cdetect -y 1
# 2) 反编译正在 boot 的 dtb,看 goodix 节点 reg
dtc -I dtb -O dts /home/charliechen/tftp/imx6ull-aes.dtb 2>/dev/null | grep -A3 'gt9147@'
# 3) 改完三处源后,快速重编单个 dtb
cd third_party/linux_mainline
make ARCH=arm imx_aes_mainline_defconfig
make ARCH=arm nxp/imx/imx6ull-aes.dtb
# 4) 备份 + 部署 + 验证
cp -n /home/charliechen/tftp/imx6ull-aes.dtb /home/charliechen/tftp/imx6ull-aes-before-goodix-fix.dtb
cp arch/arm/boot/dts/nxp/imx/imx6ull-aes.dtb /home/charliechen/tftp/imx6ull-aes.dtb
dtc -I dtb -O dts /home/charliechen/tftp/imx6ull-aes.dtb 2>/dev/null | grep -A2 'gt9147@'
# 5) 重启板子后,确认 probe 成功
dmesg | grep -i goodix # 期望 Goodix-TS 1-0014,无 -6
ls /dev/input/event*
cat /proc/bus/input/devicesVerified (2026-06-29)
reg 改为 0x14、重编部署、重启板子后,触摸驱动正常 probe,/dev/input/eventX 出现,Goodix-TS 1-005d ... -6 消失。修复端到端确认。
附注:本次部署的 dtb 来自「只 apply 了触摸 patch」的内核树,比之前的 tftp dtb 少了
icm20608@0(SPI 加速度计)和sim@021b4000两个节点。纯测触摸无影响; 需要那些节点的话,把对应章节的 patch 也 apply 进树再重编。回退用imx6ull-aes-before-goodix-fix.dtb。
See Also
- 2026-06-08 WSL2 NFS Rootfs 排查记录 —— 另一个「内核侧症状、根因在 host/配置」的排查范例。
- 设备树基础 —— dts/dtsi/dtb 的关系与编译。
- 触摸章节(mainline goodix 分析) —— GT9147 驱动分析型章节。