Linux设备树

From WRTnode Wiki Site
Jump to: navigation, search
This page is a translated version of the page Device Tree Source and the translation is 100% complete.

Other languages:
English 100% • ‎中文(中国大陆)‎ 100%

一:device tree source诞生

在过去的linux内核里,如:ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,

而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info 以及各种硬件的platform_data。

Device Tree是一种描述硬件的数据结构,它起源于 OpenFirmware (OF)。

在Linux 2.6中,ARM架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx和arch/arm/mach-xxx,采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。

Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和 value。在Device Tree中,可描述的信息包括(原先这些信息大多被hard code到kernel中):

CPU的数量和类别

内存基地址和大小

总线和桥

外设连接

中断控制器和中断使用情况

GPIO控制器和GPIO使用情况

Clock控制器和Clock使用情况

它基本上就是画一棵电路板上CPU、总线、设备组成的树,Bootloader会将这棵树传递给内核,然后内核可以识别这棵树,

并根据它展开出Linux 内核中的platform_device、i2c_client、spi_device等设备,而这些设备用到的内存、IRQ等资源,也被传递给了内核, 内核会将这些资源绑定给展开的相应的设备。


二:Device Tree组成和结构

整个Device Tree牵涉面比较广,即增加了新的用于描述设备硬件信息的文本格式,又增加了编译这一文本的工具,同时Bootloader也需要支持将编译后的Device Tree传递给Linux内核。

DTS (device tree source)

.dts文件是一种ASCII 文本格式的Device Tree描述,此文本格式非常人性化,适合人类的阅读习惯。

基本上,在mips Linux,一个.dts文件对应一个mips的machine,一般放置在/target/linux/ramips/dts目录。

由于一个SoC可能对应多 个machine(一个SoC可以对应多个产品和电路板),势必这些.dts文件需包含许多共同的部分,Linux内核为了简化,

把SoC公用的部分或者 多个machine共同的部分一般提炼为.dtsi,类似于C语言的头文件。其他的machine对应的.dts就include这个.dtsi。

譬如, 对于MT762n而言,mt7620n.dtsi就被WRTNODE.dts,WRTNODE.dts所引用,WRTNODE.dts 有如下一行:

/include/ "mt7620n.dtsi"

当然,和C语言的头文件类似,.dtsi也可以include其他的.dtsi,譬如几乎所有的ARM SoC的.dtsi都引用了skeleton.dtsi。

.dts(或者其include的.dtsi)基本元素即为前文所述的结点和属性

例如:m25p80的spi flash

m25p80@0 {
               #address-cells = <1>; 
               #size-cells = <1>; 
               #compatible = "mx25l6405d"; 
               compatible = "w25q128"; 
               reg = <0 0>; 
               linux,modalias = "m25p80", "w25q128"; 
               spi-max-frequency = <10000000>; 
               partition@0 { 
                   label = "u-boot"; 
                   reg = <0x0 0x30000>; 
                   read-only; 
               }; 
               partition@30000 { 
                   label = "u-boot-env"; 
                   reg = <0x30000 0x10000>; 
                   read-only; 
               }; 
               factory: partition@40000 { 
                   label = "factory"; 
                   reg = <0x40000 0x10000>; 
                   read-only; 
               }; 
               partition@50000 { 
                   label = "firmware"; 
                   reg = <0x50000 0xfb0000>; 
               }; 
           };

m25p80@0 为结点, partition@0, factory: partition@40000 是他的子结点。 compatible 属性的组织形式为<manufacturer>,<model>,别名其实就是去掉compatible 属性中逗号前的manufacturer前缀。关于这一点,可查看drivers/spi/spi.c的源代码,函数spi_match_device()暴露了更多的细节,如果别名出现在设备spi_driver的id_table里面,或者别名与spi_driver的name字段相同,SPI设备和驱动都可以匹配上。

具体的dts介绍可以参考[1]