1.设备树,是用树状结构,来描述系统硬件信息。
这个树状结构是以根节点“/”开始的。
每一个硬件信息单元,称为节点,挂在根节点或者其它节点上。
/根节点
|-节点1
|-节点1-1
|节点1-2
|-节点2
|-节点3
2.节点结构与格式
[label:] node-name[@unit-address] {
[properties definitions]
[child nodes]
}
节点命名一般以<类型>[@<地址>]开始。在括号表示的信息中,{}为必要项目,[]为可选项。
节点{}包含若干属性,如名字、兼容性等等。属性值的格式:整形用<>表示,字符串用""表示,二进制用[]表示。
子节点相关属性未指明的情况下,父节点属性则为默认属性。
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x0>;
cpufreq_tbl = < 480000
600000
720000
816000
912000
1008000
1104000
1152000
1200000>;
clock-latency = <2000000>;
clock-frequency = <1008000000>;
};
原文件:linux-3.10\arch\arm\boot\dts\sun8iw11p1.dtsi
3.子节点与父节点
整个树是从根节点“/”开始逐级挂载的。也就是除根节点之外,其它每一个节点都必须有父节点。
/ {
model = "sun8iw11p1";
compatible = "arm,sun8iw11p1", "arm,sun8iw11p1";
interrupt-parent = <&gic>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a7";
clock-frequency = <1008000000>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x1>;
clock-frequency = <1008000000>;
};
};
引用一个节点时,需要包含整个树结构上的父节点全路径:/cpus/cpu@1.
4.文件包含
同头文件信息类似,一个dts文件可以包含引用其它文件(一般写作dtsi)的描述:
#include "sun8iw11p1-pinctrl.dtsi"
/ {
model = "sun8iw11p1";
compatible = "arm,sun8iw11p1", "arm,sun8iw11p1";
interrupt-parent = <&gic>;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a7";
clock-frequency = <1008000000>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x1>;
clock-frequency = <1008000000>;
};
};
5.常用属性
compatible = "allwinner,sunxi-udc";
指明设备兼容性。在具体的驱动程序中也有对应字段用以匹配。
static const struct of_device_id sunxi_udc_match[] = {
{.compatible = "allwinner,sunxi-udc", },
{},
};
#address-cells
#size-cells
reg = <0 0x00000000 0x04000000>,
<1 0x00000000 0x04000000>;
注意这里的#可不是代表注释。而是子结点的reg属性的address和length字段的长度。reg为设备使用的地址与取值范围。
ranges = <0xfffff400 0xfffff400 0x800>;
指明当前设备的子地址、基于父地址的映射、大小。
6.驱动匹配
struct device_driver->of_device_id->compatible字段与dts中设备的compatible 字段匹配:
static const struct of_device_id sunxi_udc_match[] = {
{.compatible = "allwinner,sunxi-udc", },
{},
};
MODULE_DEVICE_TABLE(of, sunxi_udc_match);
static struct platform_driver sunxi_udc_driver = {
.driver = {
.name = (char *)gadget_name,
.pm = UDC_PM_OPS,
.bus = &platform_bus_type,
.owner = THIS_MODULE,
.of_match_table = sunxi_udc_match,
},
.probe = sunxi_udc_probe,
.remove = sunxi_udc_remove,
};