address为1个或多个32位的整型(即cell),而length则为cell的列表或者为空(若#size-cells = 0)
reg=<1> :
这个reg是被上面的#address-cells 和#size-cells决定的
#address-cells =<1> :
决定了,以下包含的节点@后面只能接一个参数,即地址
#size-cells =<0> :
决定了,以下包含的节点里面reg= < , length> , length为空(不填)
以下包含的节点里面reg=, length 前面的参数即为@后面的参数
如果@后面只有一个参数,则为地址
如果@后面有两个参数,则为“片选+相对该片选的基地址”
如果为address-cells 为1 ,则@直接跟地址,length一般为空,即size-cells为0
当address-cells为 ,则length一般不为空,即size-cells不为0
ec@30 :
名字@器件地址
Compatible :
厂家名字,模块名字
跟i2c_device_id里面描述的名字要一致
reg=<0x30> :
器件地址,对应 ”@30”
以上是对一个i2c节点的说明,也就是i2c节点在dts里面的结构,上面的内容说到了,dts是有自己独特的结构的,具体不同的设备节点有所差异。我们在dts里面添加这些节点的时候,需要安照dts里面的规则来添加。
如果分析过程有什么错漏,大家可以提出。互相交流。这里不再多说,下面来看一个具体的应用实例。
此例子是linux里面一个控制背光的实例。首先,我们先看到dts里面描述的设备信息:
backlight {
pinctrl-names = "default";
pinctrl-0 = ;
compatible = "pwm-backlight";
lvds-bkl-enable = ;
lvds-vcc-enable = ;
pwms = ;
brightness-levels = <0 4 8 16 32 64 128 255>;
default-brightness-level = <7>;
};
pinctrl-0 :从上面lvds里面获取io脚
compatible :驱动里面会找这个名字进行匹配
lvds-bkl-enable :第四组GPIO的第六个管教,默认值为0
lvds-vcc-enable :对于gpio的描述,在include的dts里面有描述
pwms :是取寄存器的值
brightness-levels :backlight 的level
default-brightness-level :level分为7个等级
接下来,我们看看代码里面是怎样对dts节点信息进行匹配的:
driver里面会对要match的dts的分支的名字写在device_idtable里面。当遍历dtb这棵树的时候,能找到与下面“compatible”名字相同的节点的名字,就匹配成功。
static struct of_device_id pwm_backlight_of_match[] = {
{ .compatible = "pwm-backlight" },
{ }
};
在backlight的驱动里面,当执行到probe函数的时候,会对dts里面几个管脚进行匹对,取值。其中,要注意以下几个函数的用法:
of_get_named_gpio
of_find_property
of_property_read_u32_array
of_property_read_u32
其实这几个函数的作用,做的事情都是这样一个过程:在匹配成功的节点里面寻找到函数参数里面匹配的字符串,然后读取后面的数值。至于这几个函数的源码,可以到“scripts/dtc”里面查看。
lvds_vcc_enable = of_get_named_gpio(node, "lvds-vcc-enable", 0);
if (lvds_vcc_enable > 0)
{
ret = gpio_request(lvds_vcc_enable,"lvds_vcc_enable");
if (ret < 0) {
printk("request lvds_vcc_enable failed: %d\n", ret);
return ret;
}
gpio_direction_output(lvds_vcc_enable, 1);
}
lvds_bkl_enable = of_get_named_gpio(node, "lvds-bkl-enable", 0);
if (lvds_bkl_enable > 0)
{
ret = gpio_request(lvds_bkl_enable,"lvds_bkl_enable");
if (ret < 0) {
printk("request lvds_bkl_enable failed: %d\n", ret);
return ret;
}
gpio_direction_output(lvds_bkl_enable, 1);
}
/* determine the number of brightness levels */
prop = of_find_property(node, "brightness-levels", &length);
if (!prop)
return -EINVAL;
data->max_brightness = length / sizeof(u32);
/* read brightness levels from DT property */
if (data->max_brightness > 0) {
size_t size = sizeof(*data->levels) * data->max_brightness;
data->levels = devm_kzalloc(dev, size, GFP_KERNEL);
if (!data->levels)
return -ENOMEM;
ret = of_property_read_u32_array(node, "brightness-levels",
data->levels,
data->max_brightness);
if (ret < 0)
return ret;
ret = of_property_read_u32(node, "default-brightness-level",
&value);
上面一段代码就是读取dts数据,初始化管教,或数组的过程。
当然,dts还有include,定义变量,引用等一些用法。具体可以参考“arch/arm/boot/dts/”下的文件进行配置。