ARM devicetree起源
过去ARM Linux中,充斥着大量的垃圾代码,这些设备代码与对应公司单板启动或运行细节强绑定,无法复用和移植。同时内核中没有规范来引导,导致代码越来越臃肿。最终因为Tony Lindgren,内核OMAP development tree的维护者,发送了一个邮件给Linus,请求提交OMAP平台代码修改,并附带修改以及如何解决merge conficts,让linus发出怒吼“Gaah.Guys, this whole ARM thing is a f*cking pain in the ass.”(linus对arm这样代码肯定深恶痛绝已久)。
最终经过讨论,对ARM平台相关code做出相关规范:
- ARM的核心代码仍然保存在arch/arm目录下;
2. ARM SoC core architecture code保存在arch/arm目录下;
3. ARM SOC的周边外设模块的驱动保存在drivers目录下;
4. ARM SOC的特定代码在arch/arm/mach-xxx目录下;
5. ARM SOC board specific的代码被移除,由DeviceTree机制来负责传递硬件拓扑和硬件资源信息。
本质上,Device Tree改变了原来用hardcode方式将硬件设备配置信息嵌入到内核代码的方法,改用bootloader传递一个DB的形式。
DTS知识介绍
Arm系统启动,硬件设备可以通过DTS(devicetree)或ACPI引导初始化,这里只讲DTS方式,ACPI是由BIOS配置。

如上图,一般来说,arm内核通过dts引导启动,需要内核Image、dtb和filesystem,其中dtb是由dts通过dtc工具生成,里面包括初始化设备的硬件信息。内核Image启动过程中会解析dtb中内容,并根据信息初始化设备平台。这里提一句,dts由虽然由用户配置,但是配置必须与硬件信息相匹配,否则会出现初始化失败或设备部分功能不正常的问题。
DTS描述
Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。在Device Tree中,可描述的信息包括(原先这些信息大多被hard code到kernel中),CPU的数量和类别、内存基地址和大、timer时钟、外设连接、中断配置、串口等。内核在启动过程中会解析每个node的硬件配置信息,根据这些信息初始化设备。
举例,如下是arm gicv3中断控制器的节点配置信息(来源Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.txt):
gic: interrupt-controller@2cf00000 {
compatible = "arm,gic-v3";
#interrupt-cell