4、设备树(Device Tree)与ACPI:Android设备树(DTS)格式演变,以及如何适配不同内核版本
在Android多内核版本驱动移植中,设备树(Device Tree)与ACPI(高级配置与电源接口)是描述硬件拓扑与资源分配的核心机制。Android生态以ARM64为主,设备树(DT)是主流;ACPI主要用于x86及部分服务器级ARM平台。本章聚焦设备树格式在内核版本间的演变、DTS/DTB/DTBO的编译与加载差异,以及跨版本适配的关键要点。
4.1 设备树基础与Android中的角色
设备树是一种描述硬件配置的数据结构,由DTS(Device Tree Source)编译为DTB(Device Tree Blob),在系统启动时由Bootloader传递给内核。Android从早期版本开始就深度依赖设备树来管理外设、时钟、中断、DMA等资源。
以下SVG展示了设备树在Android启动流程中的位置与数据流:
4.2 DTS格式演变与内核版本对应
设备树规范由ePAPR(Power.org标准)演进到Devicetree Specification v0.1~v0.4。Linux内核版本升级时,DTS的语法、绑定、宏定义方式均有变化。以下表格总结了关键版本差异:
| 内核版本 | DTS格式/特性 | 关键变化 | 影响范围 |
|---|---|---|---|
| 4.4 ~ 4.9 | 传统DTS + 简单绑定 | 使用#include |
GPIO、I2C、SPI控制器 |
| 4.14 ~ 4.19 | 引入DT overlay支持 | 新增dtbo.img分区;overlay DTS使用/plugin/;target-path语法 | 设备树碎片化、模块化 |
| 5.4 ~ 5.10 | YAML绑定(DT schema) | 引入dtschema工具;绑定文件从.txt转为.yaml;compatible字符串规范化 | 驱动绑定验证、编译时检查 |
| 5.15 ~ 6.x | ACPI与DT共存增强 | 支持ACPI IORT/PPT;DT phandle+link;中断映射标准化 | 多平台兼容、虚拟化 |
4.3 DT Overlay机制与跨版本适配
DT Overlay允许在运行时或编译时对基础设备树进行增量修改,避免为每个硬件变体维护完整DTS。Android从内核4.14开始引入DTBO(Device Tree Blob for Overlay)分区,与主DTB分离。
以下SVG展示了overlay的合并流程:
Overlay DTS的典型写法(适用于内核5.4+):
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
/plugin/;
/ {
fragment@0 {
target-path = "/soc/i2c@7e804000";
__overlay__ {
status = "okay";
clock-frequency = <400000>;
eeprom@50 {
compatible = "atmel,24c02";
reg = <0x50>;
};
};
};
};
4.4 中断与GPIO控制器描述差异
不同内核版本对中断控制器和GPIO控制器的设备树绑定有细微变化,直接影响驱动中断申请与GPIO操作。以下表格对比了常见差异:
| 特性 | 内核4.x | 内核5.x | 适配要点 |
|---|---|---|---|
| 中断控制器 | interrupt-parent = <&gic>; | interrupt-parent = <&intc>; 或使用interrupt-map | 检查GIC版本(v2/v3)的interrupt-cells差异 |
| GPIO hog | gpio-hog; 直接写在节点内 | gpio-hog; 需配合pinctrl | 5.x要求hog节点必须有pinctrl-0属性 |
| DMA | dma-ranges; 使用dma-coherent | dma-ranges; 新增dma-noncoherent | 5.10+需要显式声明cache一致性 |
| 时钟 | clocks = <&clk 1>; | clocks = <&clk 1>; 新增assigned-clock-rates | 5.x推荐使用assigned-clock-parents |
以下SVG展示了中断控制器在设备树中的层级关系:
4.5 ACPI在Android中的角色与适配
ACPI主要用于x86 Android设备(如Intel Atom、AMD平台)以及部分ARM服务器。Android内核从4.19开始增强了对ACPI 6.2+的支持,包括IORT(I/O Remapping Table)、PPT(Platform Properties Table)等。
ACPI与设备树的主要对比:
| 特性 | 设备树(DT) | ACPI |
|---|---|---|
| 描述方式 | 文本DTS编译为二进制DTB | ASL编译为AML字节码 |
| 动态修改 | 支持overlay(dtbo) | 支持DSDT overlay |
| 驱动匹配 | compatible字符串 | HID/CID(硬件ID/兼容ID) |
| 电源管理 | 通过驱动自身实现 | ACPI _PS0/_PS3方法 |
| Android支持 | 主流(ARM64) | 次要(x86/服务器) |
of_property_read_*和acpi_dev_get_property分别读取,避免硬编码。内核5.10+提供了device_property_read_*统一API,可自动适配两种固件接口。
4.6 跨版本适配清单与最佳实践
以下清单总结了从内核4.4到6.x的设备树适配要点:
- DTS语法检查: 使用
dtc -I dts -O dtb编译时,务必指定-@标志以生成phandle信息,否则overlay无法工作。 - compatible字符串规范化: 从内核5.4开始,推荐使用
vendor,device格式,并在绑定文档(.yaml)中注册。 - 中断映射: 如果使用GICv3,注意
interrupt-cells为3(中断类型、编号、标志),而GICv2为2。 - GPIO命名: 内核5.x废弃了
gpios属性中的#gpio-cells隐式定义,必须显式声明。 - 时钟频率: 使用
assigned-clock-rates替代在驱动中硬编码频率,提高可移植性。 - ACPI共存: 在驱动中同时实现
of_match_table和acpi_match_table,并使用MODULE_DEVICE_TABLE导出。
target = <&phandle>时,如果基础DTB未编译-@选项,phandle符号表缺失,overlay加载会失败。建议在Makefile中统一添加DTC_FLAGS += -@。
以下SVG总结了跨版本适配的决策流程:
4.7 小结
设备树与ACPI是Android驱动与硬件平台之间的“翻译官”。内核版本升级带来的DTS格式变化、overlay机制引入、YAML绑定规范化以及ACPI增强,都要求驱动开发者具备前瞻性的适配思维。掌握跨版本兼容写法、善用统一API、严格遵循绑定规范,是确保驱动在多内核版本间平滑移植的关键。