跳转至

DTS 移植方法论(跨路线)

本文提炼 GEC RK3568 板级 DTS 移植中反复验证有效的方法,覆盖 factory 4.19 参考资料、并行维护的 BSP 5.10 / 6.1、Mainline 参考实现和暂缓的 BSP 6.6 规划。 它是「怎么改、怎么判断对错」的 playbook;「改了什么」的具体落盘见 rockchip-6.1/01_dts_override.mdrockchip-5.10/02_device_tree.md。 本文不重复列节点,只沉淀方法。

BSP 6.1 当前 DTS 派生层结构

图中以 BSP 6.1 当前文件为例:三层 GEC 派生文件对应 EVB1 的三个层级,共享 SoC / Linux 基线;这不是“只新增一个 override 文件”的结构。

1. 核心思想:区分共享基线与 GEC 派生层

不能用 rk3568-evb1-* 这样的通配符判断文件归属。当前 6.1 的 rk3568-evb1-gec-v11.dtsi 虽然带 evb1 前缀,但它是 GEC 自有板级文件,本来就需要随板级适配继续修改。

当前规则是:

  • 共享 Rockchip 基线rk3568.dtsirk356x.dtsirk3568-linux.dtsi,以及作为复制来源的原版 EVB 文件。当前结构复用这些文件,不把 GEC 板级差异直接写进去。
  • GEC 派生文件:文件名明确带 gec,包括 rk3568-evb1-gec-v11-linux.dtsrk3568-evb1-gec-v11.dtsirk3568-evb-gec.dtsi。这些是当前应维护、可修改的板级文件。
  • 判断依据是文件来源和职责,不是前缀rk3568-evb-gec.dtsi 沿用 5.10 的旧命名,但它属于 GEC;rk3568-evb1-gec-v11.dtsi 采用 EVB1 风格命名,也仍属于 GEC。

6.1 当前不是“一个 override + 一个薄入口”,而是三个 GEC 派生层共同替代原 EVB1 的相应层级:

Rockchip 原版 EVB1                       GEC 6.1 派生版
rk3568-evb1-ddr4-v10-linux.dts    ->     rk3568-evb1-gec-v11-linux.dts
rk3568-evb1-ddr4-v10.dtsi         ->     rk3568-evb1-gec-v11.dtsi
rk3568-evb.dtsi                    ->     rk3568-evb-gec.dtsi

rk3568.dtsi / rk356x.dtsi / rk3568-linux.dtsi 继续共用

好处仍然是把 GEC 板级差异留在 GEC 文件中,便于 SDK 升级时审计、对比和迁移;但不要把这条原则误写成“所有 rk3568-evb1-* 文件都不能改”。

三类 override 动作

  1. 覆盖值(override)——改官方默认值,如 gmac1 clock_in_out output→input。
  2. 禁用错误继承(disable wrong default)——如 &sdmmc2 { status="disabled" }(GEC WiFi 在 SDMMC1,不是官方 EVB1 的 SDMMC2)。
  3. 补回独有节点(re-add)——如 i2c2 的 BH1750/EEPROM/MPU6050。

2. 三层快照区分(最容易被忽略的坑)

移植时脑子里必须同时分清三个「快照」,它们不是同一件事

快照 含义 来源
GEC 硬件 板子真实接线是什么 原理图 + factory DTS 反编译
目标 BSP 的 EVB1 Rockchip 这一版的官方默认是什么 明确选定的原版 EVB1 基线,如 6.1 的 rk3568-evb1-ddr4-v10.dtsi,不使用会匹配 GEC 文件的宽泛通配符
factory 4.19 出厂那版是什么 反编译 factory boot.img 的 DTB

关键教训4.19 EVB1 ≠ 6.1 EVB1(GMAC delay 0x41/0x1e→0x4f/0x26、WiFi sdmmc1→sdmmc2、i2c2 传感器被删、NPU 节点从 rk3568.dtsi 挪到 rk356x.dtsi……)。所以 GEC 的 override 必须描述「GEC 硬件 vs 目标 BSP 的 EVB1」,绝不能盲抄 4.19 的 GEC DT

3. 系统性 diff + 三类分类

从 factory DTB 提取板级差异,不要靠肉眼逐行看,用脚本做 full-path 对比:

反编译 factory DTB → full-path diff(vs 目标 BSP EVB1 的 DTB)
→ phandle 经 __symbols__ 解析成 LABEL(稳定词汇,避免误判)
→ 每个 diff 分三类
分类 含义 处置
BOARD_DELTA 板级真实差异(GEC 独有) ✅ 落盘到 override 层
BSP_DRIFT BSP 版本演进(如 serial@* compatible 扩展、usb3 phy 补丁) ❌ 不落盘(版本差异,非板级)
ARTIFACT phandle 重编号等噪声 ❌ 忽略

实例:backlight pwms period 1000000ns = BOARD_DELTA(落盘);pcie@fe26* compatible 扩展 = BSP_DRIFT(不落盘);wireless-wlan WIFI,host_wake_irq phandle 0xb4 vs 0xb3 = ARTIFACT(忽略)。

4. 参考纪律:factory DTS 是「参考」,不是「真理」

factory 4.19 DTS 是唯一反映 GEC 真实接线的权威参考,但它不可盲信

  1. 已证实的 factory 错误
  2. vcc5v0_otg 漏了 enable-active-high(与硬件 SY6280 高有效 + fixed-regulator 语义矛盾)。
  3. GT911 irq-gpios 极性(factory 的 flag 是 open-drain 位,不是极性位,曾被误读)。
  4. 规则:与原理图/硬件冲突时,信硬件,不信 factory DTS
  5. 版本坑:本地 4.19 树是 4.19.219,但真正能跑的 factory 是 4.19.232——本地树不是可信 baseline,不能拿它对比 6.1/5.10 的 NPU 行为。
  6. 改没改先看 git:判断 SDK 里的 dtsi 是否被改,用 git status/git diff HEAD实际编译的那份,别分析用户说「没用」的 backup 拷贝。

5. GPIO 极性约定

DTS 里 GPIO 引用元组(如 <&gpio3 RK_PC2 0x00>)的末位是 GPIO_ACTIVE_* flag

  • 0 = GPIO_ACTIVE_HIGH
  • 1 = GPIO_ACTIVE_LOW

(Linux dt-bindings/gpio/gpio.h 标准,GPIO_ACTIVE_HIGH/GPIO_ACTIVE_LOW 宏。)

两条易混的坑

  1. 这个 flag 不是 IRQ 触发类型——IRQ 类型在 interrupts 属性里,不在 GPIO 元组末位。0x04 这类是 GPIO_LINE_OPEN_DRAIN(bit2),不是极性。
  2. fixed-regulatorenable-active-high 属性是另一个概念,别和 GPIO flag 混(见 §4 的 VBUS 案例)。

曾在 4.19 DTB 审计时把这个搞反过(0x01 读成 HIGH),被纠正。审计极性时务必回查 0=HIGH / 1=LOW

6. 证据链:DTS 写对 ≠ 功能完成

每层证据按「最弱成立」记录,不要跳级(详见 rockchip-5.10/02_device_tree.md11_debug_methodology.md):

source DTS → built DTB → running DTB → bus device/client → driver bind
→ subsystem register → sysfs/dev node → runtime behavior
  • status = "okay" 只说明意图,不代表驱动绑定、更不代表用户态可用。
  • 判断「设备是否 probe」以 /sys/bus/i2c/devices/i2cdetect 板端实况为准,别只看 grep 过的日志(BH1750「消失」误判的教训)。

7. 常见 gotcha 清单

gotcha 正确做法
GMAC tx/rx_delay GEC 保持 0x41/0x1e不要采 6.1 EVB1 的 0x4f/0x26
GMAC 命名 BSP 5.10 里 fe010000=gmac1(真口)、fe2a0000=gmac0(空口),与主线相反;判断一律以 reg 地址为准,别信 gmac0/gmac1 名字;BSP 用单数 reset-gpio(不是 reset-gpios
WiFi SDMMC GEC 在 sdmmc1(不是 EVB1 的 sdmmc2),要 disable sdmmc2
NPU 节点位置 6.1 从 rk3568.dtsi 挪到 rk356x.dtsi;compatible rockchip,rk3568-rknpu 跨版本不变
Touch 属性命名 goodix,gt911irq-gpios/reset-gpiosgoodix,gt1xgoodix,irq-gpio/goodix,rst-gpio
GT911 中断 6.1 goodix.cclient->irq(来自 interrupts),调用 gpiod_to_irq——节点必须带 interrupt-parent+interrupts
GT911 地址选择 reg=0x5dirq-gpios 必须 GPIO_ACTIVE_HIGH(address-select 逻辑反相)
背光 PWM 索引 丝印 pwm4 可能对应 pwm@fe6e0000 的索引 +1,核对 pinctrl 再写
WiFi 控电 GEC 用单一 sdio_pwrseq reset-gpios不要再加 WIFI,poweren_gpio(双重控电)

(每条的具体落盘见 rockchip-6.1/01_dts_override.md。)

8. 工具

  • dtc 反编译dtc -I dtb -O dts -o out.dts in.dtb(uutils 的 dtc 用 tail -n N,不是 -N)。
  • DTB 对比脚本(已沉淀到 scripts/dtb/,用法见 scripts/dtb/README.md):dtb2dts.pydtb_cmp.pydtb_cmp2.pyextract_cfg_dtb.pyunpack_boot.py
  • 板端只读快照(已入库):scripts/check_bsp_5_10.shscripts/check_i2c_bindings.sh
  • 交叉编译工具链:全量构建用 /opt GCC 15.2(aarch64-none-linux-gnu-);4.19-SDK GCC 6.3.1 只能做轻量任务(全量会被 CONFIG_WERROR=y 卡死)。