linux设备树

1.设备树文件在linux中的位置:

imx-linux4.9.88\arch\arm\boot\dts(更新设备树dtb,/boot/可直接替换)

系统启动以后可以在根文件系统里面看到设备树的节点信息。在/proc/device-tree/目录下存放着设备树信息。

2.dts与dtb的区别:

.dts相当于.c,就是DTS源码文件。
.dtb相当于bin文件,或可执行文件。

3.设备树源码中常用的几种数据形式如下所示:
①、字符串
compatible = "arm,cortex-a7";
上述代码设置 compatible 属性的值为字符串“arm,cortex-a7”。
②、 32 位无符号整数
reg = <0>;
上述代码设置 reg 属性的值为 0, reg 的值也可以设置为一组值,比如:
reg = <0 0x123456 100>;
③、字符串列表
属性值也可以为字符串列表,字符串和字符串之间采用“,”隔开,如下所示:
compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";

static const struct of_device_id 12345_dt_ids[] = {
   { .compatible = "fsl(厂商),led(模块对应的驱动名字)"(设备树文件中.compatible的内容), },
};

static struct platform_driver imx_xxx_driver = {
 .probe = xxx_probe函数,
 .remove =xxx_remove函数,
 .driver = {                                                                       
               .name = "与硬件平台设备名字相对应",
               .of_match_table = 12345_dt_ids(数组名),
             },
};

4.标准属性 

1)compatible 属性
compatible 属性也叫做“兼容性”属性。compatible 属性的值是一个字符串列表, compatible 属性用于将设备和驱动绑定起来。

字符串列表用于选择设备所要使用的驱动程序, compatible 属性的值格式如下所示:
"manufacturer,model"
其中 manufacturer 表示厂商, model 一般是模块对应的驱动名字。

compatible = "manufacturer,model1","manufacturer,model2";

这个设备首先使用第一个兼容值在 Linux 内核里面查找,看看能不能找到与之匹配的驱动文件,
如果没有找到的话就使用第二个兼容值查。

一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设
备节点的 compatible 属性值和 OF 匹配表中的任何一个值相等,那么就表示设备可以使用这个
驱动。

根节点/下面的compatible。内核启动的时候会检查是否支持此平台或机器:

arch/arm/mach-imx/mach-imx6ul.c与imx6ull-alientekemmc.dts 中根节点的 compatible 属性值
是否相同。

2) model 属性
model 属性值也是一个字符串,一般 model 属性描述设备模块信息,比如名字什么的,比
如:model = "wm8960-audio";

3) status 属性
status 属性看名字就知道是和设备状态有关的, status 属性值也是字符串,字符串是设备的
状态信息,可选的状态如表 43.3.3.1 所示:

描述
“okay”表明设备是可操作的。
“disabled”表明设备当前是不可操作的,但是在未来可以变为可操作的,比如热插拔设备
插入以后。至于 disabled 的具体含义还要看设备的绑定文档。
“fail”表明设备不可操作,设备检测到了一系列的错误,而且设备也不大可能变得可
操作。
“fail-sss”含义和“fail”相同,后面的 sss 部分是检测到的错误内容。

4、 #address-cells 和#size-cells 属性
这两个属性的值都是无符号 32 位整形, #address-cells 和#size-cells 这两个属性可以用在任
何拥有子节点的设备中,用于描述子节点的地址信息。

#address-cells 属性值决定了子节点 reg 属性中地址信息所占用的字长(32 位),

#size-cells 属性值决定了子节点 reg 属性中长度信息所占的字长(32 位)。

#address-cells 和#size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度。

5) reg 属性
 reg 属性的值一般是(address, length)。 reg 属性一般用于描述设备地址空间资源信息,一般都是某个外设的寄存器地址范围信息。

6) ranges 属性
ranges属性值可以为空或者按照(child-bus-address,parent-bus-address,length)格式编写的数字
矩阵, ranges 是一个地址映射/转换表, ranges 属性每个项目由子地址、父地址和地址空间长度
这三部分组成:
child-bus-address:子总线地址空间的物理地址,由父节点的#address-cells 确定此物理地址
所占用的字长。
parent-bus-address: 父总线地址空间的物理地址,同样由父节点的#address-cells 确定此物
理地址所占用的字长。
length: 子地址空间的长度,由父节点的#size-cells 确定此地址长度所占用的字长。
7) name 属性
name 属性值为字符串, name 属性用于记录节点名字。
8)device_type 属性
device_type 属性值为字符串。此属性只能用于 cpu 节点或者 memory 节点。

5.在/根节点外有一些&cpu0这样的语句是“追加“。

6.intc: interrupt-controller@00a01000

intc是标签label;interrupt-controller@00a01000是名字。

7.Linux 内核源码中有详细的.txt 文档描述了如何添加节点,

Linux 源码目录/Documentation/devicetree/bindings。

8.驱动如何获取到设备树中节点信息。在驱动中使用OF函数获取设备树属性内容。

   驱动要想获取到设备树节点内容,首先要找到节点。

9.   获取设备树内容:

 backlight {
        compatible = "pwm-backlight";
        pwms = <&pwm1 0 5000000>;
        brightness-levels = <0 4 8 16 32 64 128 255>;
        default-brightness-level = <6>;
        status = "okay";
    };

    /*1、找到backlight节点,路径是:/backlight */
    bl_nd = of_find_node_by_path("/backlight");
    if (bl_nd == NULL) {    /* 失败 */
        ret = -EINVAL;
        goto fail_findnd;
    }

    /* 2、获取属性 */
    comppro = of_find_property(bl_nd, "compatible", NULL);
    if (comppro == NULL) {    /* 失败 */
        ret = -EINVAL;
        goto fail_finpro;
    } else {                /* 成功 */
        printk("compatible=%s\r\n", (char*)comppro->value);
    }

    ret = of_property_read_string(bl_nd, "status", &str);
    if(ret < 0) {
        goto fail_rs;
    } else {
        printk("status=%s\r\n", str);
    }

    /*3、 获取数字属性值 */
    ret = of_property_read_u32(bl_nd, "default-brightness-level", &def_value);
    if(ret < 0) {
        goto fail_read32;
    } else {
        printk("default-brightness-level=%d\r\n", def_value);
    };

    /* 4、获取数组类型的属性 */
    elemsize = of_property_count_elems_of_size(bl_nd, "brightness-levels", sizeof(u32));
    if(elemsize < 0) {
        ret = -EINVAL;
        goto fail_readele;
    } else {
        printk("brightness-levels elems size = %d\r\n", elemsize);
    };

    /* 获取数组 */
    ret = of_property_read_u32_array(bl_nd, "brightness-levels", brival, elemsize);
    if(ret < 0) {
        goto fail_read32array;
    } else {
        for(i = 0; i < elemsize; i++) {
            printk("brightness-levels[%d] = %d\r\n", i, *(brival + i));
        }
    }

 10. Device Tree 是一种描述硬件的数据结构,它起源于 OpenFirmware(OF)。在 Linux2.6 中,ARM 架构的板机硬件细节过多地被硬编码在 arch/arm/plat-xxx 和 arch/arm/mach-xxx,采用 Device Tree 后,许多硬件的细节可以直接透过它传递给 Linux,而不再需要在 kernel 中进行大量的冗余编码。

    Device Tree 由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子节点。所谓属性,其实就是成对出现的 name 和 value 。

    在 Device Tree 中,可描述的信息包括(原先这些信息大多被硬编码到 kernel 中):

  • CPU的数量和类别
  • 内存基地址和大小
  • 总线和桥
  • 外设连接
  • 中断控制器和中断使用情况
  • GPIO控制器和GPIO使用情况
  • Clock控制器和Clock使用情况

    它基本上就是画一棵电路板上(CPU、总线、设备组成)的树,Bootloader 会将这棵树传递给内核,然后内核可以识别这棵树,并根据它展开出 Linux 内核中的 platform_device、i2c_client、spi_device等设备,而这些设备用到的内存、IRQ 等资源,也被传递给了内核,内核会将这些资源绑定给展开的相应的设备。

    .dts 文件是一种 ASCII 文本格式的 Device Tree 描述。基本上,在 ARM Linux 中,一个 .dts 文件对应一个 ARM 的 machine,一般放置在内核的 arch/arm/boot/dts/ 目录。由于一个 SOC 可能对应多个 machine(一个SOC可以对应多个产品和电路板),势必这些 .dts 文件需包含许多共同的部分,Linux 内核为了简化,把 SOC 公用的部分或者多个 machine 共同的部分一般提炼为 .dtsi,类似于C语言的头文件。其他的 machine 对应的 .dts 就是 include 这个 .dtsi 。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值