精华内容
下载资源
问答
  • linux 设备树

    千次阅读 2017-09-01 22:19:36
    linux 设备树参考地址 http://blog.csdn.net/green1900/article/details/45646095 http://www.cnblogs.com/xiaojiang1025/p/6131381.html http://blog.csdn.net/21cnbao/article/details/84575461.为什么要使用...

    linux 设备树


    参考地址
    http://blog.csdn.net/green1900/article/details/45646095
    http://www.cnblogs.com/xiaojiang1025/p/6131381.html
    http://blog.csdn.net/21cnbao/article/details/8457546


    1.为什么要使用设备树(Device Tree)?

    在以前的内核源码中,存在大量对板级细节信息描述的代码,这些代码充斥在/arch/arm/plat-xxx和/arch/arm/mach-xxx目录,对内核而言这些platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data绝大多数纯属垃圾冗余代码。为了解决这一问题,ARM内核版本3.x之后引入了原先在Power PC等其他体系架构已经使用的Flattened Device Tree。DTS不是arm的专利

    在使用了设备树后,对于同一SOC的不同主板,只需更换设备树文件.dtb即可实现不同主板的无差异支持,而无需更换内核文件。


    2.设备树的的组成和结构

    设备树可以描述的信息包括了
    1. CPU的数量和类别、
    2. 内存基地址和大小、
    3. 总线和桥、
    4. 外设连接、
    5. 中断控制器和中断使用情况、
    6. GPIO控制器和GPIO使用情况、
    7. Clock控制器和Clock使用情况。
    需要注意的是,设备树对于可热插拔的热备不进行具体描述,它只描述用于控制该热插拔设备的控制器

    2.1设备树的组成

    设备树包含了DTC(device tree compiler) , DTS(device tree resource) 和 DTB(device tree blob),简单来说,dts是源码,dtc是编译器,dtb是生成的可执行文件
    此处输入图片的描述

    2.1.1 DTS和DTSI

    .dts和.dtsi是一种ASCII文本的设备树描述,此文本格式非常适合人们阅读,基本上,一个.dts对应一种ARM设备,放在arch/arm/boot/dts目录,由于一个soc对应好多个不同的开发板,每个开发板有一个.dts,所以这些dts势必有共同部分,为了减少代码的屯余,设备树将这些共同部分提炼保存在dtsi中,供不同的dts使用,dtsi文件类似于c语言的头文件
    

    2.1.2 DTC

    DTC为编译工具,它可以将.dts文件编译成.dtb文件。DTC的源码位于内核的scripts/dtc目录,内核选中CONFIG_OF,编译内核的时候,主机可执行程序DTC就会被编译出来

    2.1.3 DTB

    DTB设备由DTC编译后的二进制格式的设备树描述,可以由linux内核解析,uboot这样的bootloader也可以识别.dtb,有两种使用方式,一种是bootloader启动内核过程中会先读取dtb到文件中;第二种是把dtb和zImage打包在一起做成一个印象文件,firefly-3399就是采用这种方式,打包生成了boot.img

    2.1.4 绑定(bingding)

    对于Device Tree中的结点和属性具体是如何来描述设备的硬件细节的,一般需要文档来进行讲解,文档的后缀名一般为.txt。这些文档位于内核的Documentation/devicetree/bindings目录,其下又分为很多子目录

    2.1.5 Bootloader 使用dtb

    在Uboot中,可以从NAND、SD或者TFTP等任意介质将.dtb读入内存,假设.dtb放入的内存地址为0x71000000,之后可在Uboot运行命令fdt addr命令设置.dtb的地址,如:
    U-Boot> fdt addr 0x71000000
    fdt的其他命令就变地可以使用,如fdt resize、fdt print等
    对于ARM来讲,可以透过bootz kernel_addr initrd_address dtb_address的命令来启动内核,即dtb_address作为bootz或者bootm的最后一次参数,第一个参数为内核映像的地址,第二个参数为initrd的地址,若不存在initrd,可以用 -代替,第三个就是dtb地址

    2.2设备树框架

    设备树用树状结构描述设备信息,它有以下几种特性
    1. 每个设备树文件都有一个根节点,每个设备都是一个节点。
    2. 节点间可以嵌套,形成父子关系,这样就可以方便的描述设备间的关系。
    3. 每个设备的属性都用一组key-value对(键值对)来描述。
    4. 每个属性的描述用;结束


    3. 设备树语法

    设备树是一颗树,书上的每个节点由节点和属性组成,属性是键值对

    下面这个是rk3399-fpga.dts

    #include "rk3399.dtsi"  //包含了公共部分
    / {
            model = "Rockchip RK3399 FPGA Board";
            compatible = "rockchip,fpga", "rockchip,rk3399"; //根节点兼容性分析,下面具体分析
            chosen {
                    bootargs = "init=/init console=uart,mmio32,0xff1a0000";
            };
            memory@00000000 { //子节点  memory@00000000节点名
                    device_type = "memory";
                    reg = <0x0 0x00000000 0x0 0x20000000>;
            };
    };
    &uart2 { //使用了引用
            status = "okay";
            clocks = <&xin24m>, <&xin24m>;
    };
    

    3.1根节点兼容性

    compatible = "rockchip,fpga", "rockchip,rk3399";
    上面是根节点的兼容属性,定义了整个系统(设备级别)的名称,通过这个属性就可以判断出它启动的是什么设备。它的组织形式是&lt;manufacture&gt;&lt;model&gt;,在实际中一般包括两个或两个以上的兼容字符串,上面第一个是"rockchip,fpga",第二个是"rockchip,rk3399",我们来看第二个,manufacture是板子级别的名字,“rockchip”代表的是瑞芯微公司,model是芯片级别的,“rk3399”是瑞芯微公司一个soc的名称
    

    我们从源码中找出rk3399的两个dts,可以看出第一个兼容字符串的model不同,第二个完全相同

    rk3399-firefly-linux.dts
    compatible = "rockchip,rk3399-firefly-linux", "rockchip,rk3399";
    rk3399-fpga.dts
    compatible = "rockchip,fpga", "rockchip,rk3399";

    3.2节点名

    理论个节点名只要是长度不超过31个字符的ASCII字符串即可,Linux内核还约定设备名应写成形如[@]的形式,其中name就是设备名,最长可以是31个字符长度。unit_address一般是设备地址,用来唯一标识一个节点
    Linux中的设备树还包括几个特殊的节点,比如chosen,chosen节点不描述一个真实设备,而是用于firmware传递一些数据给OS,比如bootloader传递内核启动参数给内核

    chosen{
        bootargs = "console=ttySAC2,115200";
        stdout-path=&serial_2;
    };

    3.3引用

    当我们找一个节点的时候,我们必须书写完整的节点路径,这样当一个节点嵌套比较深的时候就不是很方便,所以,设备树允许我们用下面的形式为节点标注引用(起别名),借以省去冗长的路径。这样就可以实现类似函数调用的效果

    3.KEY

    在设备树中,键值对是描述属性的方式,比如,Linux驱动中可以通过设备节点中的”compatible”这个属性查找设备节点
    inux设备树语法中定义了一些具有规范意义的属性,包括:compatible, address, interrupt等,这些信息能够在内核初始化找到节点的时候,自动解析生成相应的设备信息。此外,还有一些Linux内核定义好的,一类设备通用的有默认意义的属性,这些属性一般不能被内核自动解析生成相应的设备信息,但是内核已经编写的相应的解析提取函数,常见的有 “mac_addr”,”gpio”,”clock”,”power”。”regulator” 等等。

    3.1.compatible

    设备节点中对应的节点信息已经被内核构造成struct platform_device。驱动可以通过相应的函数从中提取信息。主要有三种方法提取信息

        1、compatible属性是用来查找节点
        2、通过节点名查找指定节点
        3、节点路径查找指定节点

    看一个使用compatible提取属性的例子

    #dts
        gpio_demo: gpio_demo {
            status = "okay";
            compatible = "firefly,rk3399-gpio";                  
        };
    #驱动代码
    static struct of_device_id firefly_match_table[] = {
        { .compatible = "firefly,rk3399-gpio",}, //完全相同
        {}, //最后一个成员一定是空,因为相关的操作API会读取这个数组直到遇到一个空。
    };

    3.2address

    • #address-cells,用来描述子节点”reg”属性的地址表中用来描述首地址的cell的数量
    • #size-cells,用来描述子节点”reg”属性的地址表中用来描述地址长度的cell的数量。
            pinctrl: pinctrl {
                    compatible = "rockchip,rk3399-pinctrl";
                    #address-cells = <0x2>;
                    #size-cells = <0x2>;
                    gpio0: gpio0@ff720000 {
                            compatible = "rockchip,gpio-bank";
                            reg = <0x0 0xff720000 0x0 0x100>;
                            //前两个数字表示一个地址0x0 0xff720000
                            //后两个数字表示一个地址跨度 0x100
                    };
                ...
        }

    3.3interrupts

    一个计算机系统中大量设备都是通过中断请求CPU服务的,所以设备节点中就需要在指定中断

    • interrupt-controller 一个空属性用来声明这个node接收中断信号,即这个node是一个中断控制器
    • #interrupt-cells,是中断控制器节点的属性,用来标识这个控制器需要几个单位做中断描述符,用来描述子节点中”interrupts”属性使用了父节点中的interrupts属性的具体的哪个值。一般,如果父节点的该属性的值是3,则子节点的interrupts一个cell的三个32bits整数值分别为:<中断域 中断 触发方式>,如果父节点的该属性是2,则是<中断 触发方式>
    • interrupt-parent,标识此设备节点属于哪一个中断控制器,如果没有设置这个属性,会自动依附父节点的
    • interrupts,一个中断标识符列表,表示每一个中断输出信号

    3.4gpio

    • gpio-controller,用来说明该节点描述的是一个gpio控制器
    • #gpio-cells,用来描述gpio使用节点的属性一个cell的内容,即 `属性 = <&引用GPIO节点别名 GPIO标号 工作模式>
    firefly-gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;          /* GPIO0_B4 */
    firefly-irq-gpio = <&gpio4 29 IRQ_TYPE_EDGE_RISING>;  /* GPIO4_D5 */  

    4.DTB的加载过程

    参考地址
    http://blog.csdn.net/green1900/article/details/45646095
    此处输入图片的描述
    http://blog.csdn.net/lichengtongxiazai/article/details/38941913
    此处输入图片的描述

    总的归纳为:

    ① kernel入口处获取到uboot传过来的.dtb镜像的基地址

    ② 通过early_init_dt_scan()函数来获取kernel初始化时需要的bootargs和cmd_line等系统引导参数。

    ③ 调用unflatten_device_tree函数来解析dtb文件,构建一个由device_node结构连接而成的单向链表,并使用全局变量of_allnodes保存这个链表的头指针。

    ④ 内核调用OF的API接口,获取of_allnodes链表信息来初始化内核其他子系统、设备等。


    5.API调用

    #来查找在dtb中的根节点
    unsigned long __init of_get_flat_dt_root(void)
    
    # 根据deice_node结构的full_name参数,在全局链表of_allnodes中,查找合适的device_node
    struct device_node *of_find_node_by_path(const char *path)
    
    #若from=NULL,则在全局链表of_allnodes中根据name查找合适的device_node
    struct device_node *of_find_node_by_name(struct device_node *from,const char *name)
    
    #根据设备类型查找相应的device_node
    struct device_node *of_find_node_by_type(struct device_node *from,const char *type)
    
    # 根据compatible字符串查找device_node
    struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compatible)
    
    #根据节点属性的name查找device_node
    struct device_node *of_find_node_with_property(struct device_node *from,const char *prop_name)
    
    #根据compat参数与device node的compatible匹配,返回匹配度
    int of_device_is_compatible(const struct device_node *device,const char *compat)
    
    #获得父节点的device node
    struct device_node *of_get_parent(const struct device_node *node)
    
    #读取该设备的第index个irq号
    unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
    
    #读取该设备的第index个irq号,并填充一个irq资源结构体
    int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
    
    #获取该设备的irq个数
    int of_irq_count(struct device_node *dev)
    

    展开全文
  • Linux设备树

    2018-03-30 20:38:53
    设备树 组成 DTS有一系列node(节点)和property(属性),节点可以包含更多子节点,DTS主要描述设备信息 CPU的数量及类别 内存基地址和size 总线和桥 外设连接 中断 GPIO CLOCK 其有以下几种特性: 每个...

    设备树

    组成

    DTS有一系列node(节点)和property(属性),节点可以包含更多子节点,DTS主要描述设备信息

    • CPU的数量及类别
    • 内存基地址和size
    • 总线和桥
    • 外设连接
    • 中断
    • GPIO
    • CLOCK

    其有以下几种特性:

    • 每个设备树文件都有一个根节点,每个设备都是一个节点。
    • 节点间可以嵌套,形成父子关系,这样就可以方便的描述设备间的关系。
    • 每个设备的属性都用一组key-value对(键值对)来描述。
    • 每个属性的描述用;结束
    /{                                  //根节点
        node1{                          //node1是节点名,是/的子节点
            key=value;                  //node1的属性
            ...
            node2{                      //node2是node1的子节点
                key=value;              //node2的属性
                ...
            }
        }                               //node1的描述到此为止
        node3{
            key=value;
            ...
        }
    }

    节点名

    每个节点必须有节点名,格式< name>[@< unit-address>]

    • < name>:为最长31个字符的ascii字符串,一般用其代表的设备类型命名,
    • unit-address: 描述设备的地址,一般情况下,其提供访问设备的基地址,节点的reg property也用此参数,见下文。

    引用

    和c语言一样支持引用,如果按照树结构书写嵌套比较深,会十分不方便,可以&节点名来省去路径,相同节点不同属性信息会被合并,相同节点相同的属性会被重写

    &cpu{
        cpu0-supply = <&buck2_reg>;
    };

    KEY

    键值对是描述设备属性的方式,eg:Linux驱动中可以通过设备节点中的“compatible”这个属性查找设备节点。
    其包括包括:compatible, address, interrupt等,这些信息能够在内核初始化找到节点的时候,自动解析生成相应的设备信息。此外,还有一些Linux内核定义好的,一类设备通用的有默认意义的属性,这些属性一般不能被内核自动解析生成相应的设备信息,但是内核已经编写的相应的解析提取函数(of_类函数),常见的有 “mac_addr”“gpio”“clock”“power”“regulator” 等等。

    - compatible

    设备树中每个节点都需要有compatible属性,compatible属性决定每一个设备驱动绑定哪一个设备,设备驱动可以利用这个相应函数读取compatible信息,利用该属性来查找节点,此外也可以通过节点名、节点路径查找指定节点。compatible是一个字符串序列,第一个字符串指定精确设备,第二字符串指定兼容设备。eg:compatible = “fsl,mpc8349-uart”, “ns16550”第一个字符串指定精确设备,第二个指定国家半导体16550 uart兼容设备。

    需要注意:驱动中用于匹配的结构使用的compatible和设备树中一模一样,否则就可能无法匹配,这里另外的一点是struct of_device_id数组的最后一个成员一定是空,因为相关的操作API会读取这个数组直到遇到一个

    static const struct of_device_id fls[] = {
      { .compatible = "fsl,mpc8349-uart", "ns16550"}
      { /*为空*/}
    };
    - address

    (几乎)所有的设备都需要与CPU的IO口相连,所以其IO端口信息就需要在设备节点节点中说明。常用的属性有

    • #address-cells,用来描述子节点“reg”属性的地址表中用来描述首地址的cell的数量,
    • #size-cells,用来描述子节点“reg”属性的地址表中用来描述地址长度的cell的数量。

    这两个属性,子节点中的“reg”就可以描述一块连续的地址区域。eg:父节点中指定了

    #address-cells = <2>;
    #size-cells = <1>;
    reg = <0 0x1046C 0x4>  //reg中的前两个数表示一个地址,即0和0x1045C,最后一个数的表示地址跨度,即是0x4
    - interrupts

    在设备中经常用到中断,设备树中中断常用属性有

    • interrupt-controller 一个空属性用来声明这个node接收中断信号,即这个node是一个中断控制器
    • #interrupt-cells,是中断控制器节点的属性,用来标识这个控制器需要几个单位做中断描述符,用来描述子节点中“interrupts”属性使用了父节点中的interrupts属性的具体的哪个值。一般,如果父节点的该属性的值是3,则子节点的interrupts一个cell的三个32bits整数值分别为:<中断域 中断 触发方式>,如果父节点的该属性是2,则是<中断 触发方式>
    • interrupt-parent,标识此设备节点属于哪一个中断控制器,如果没有设置这个属性,会自动依附父节点的
    • interrupts,一个中断标识符列表,表示每一个中断输出信号

    在内核中中断分层概念趋于流行,使内核中原本的中断源直接到中断号的方式已经很难继续发展了,所以引入了irq domain (中断域),其他的power domain,clock domain等等也是类似。系统中所有的interrupt controller会形成树状结构,对于每个interrupt controller都可以连接若干个外设的中断请求(interrupt source,中断源),interrupt controller会对连接其上的interrupt source(根据其在Interrupt controller中物理特性)进行编号(HW interrupt ID)。引入中断域后,其编号就只限定在本域内,有利于编程

    中断源--interrupt parent-->GPIO--interrupt parent-->GIC1--interrupt parent-->GIC2--...-->CPU
    gpio@101f3000 {
            compatible = "arm,pl061";
            reg = <0x101f3000 0x1000
                   0x101f4000 0x0010>;
            interrupts = < 3 0 >;
        };
    
        intc: interrupt-controller@10140000 {  // 中断控制器
            compatible = "arm,pl190";
            reg = <0x10140000 0x1000 >;
            interrupt-controller;
            #interrupt-cells = <2>; // 中断说明符有2 cells,此例中cell 1表示中断号,cell 2 表示触发方式
        };
    The 3rd cell is the flags, encoded as follows:  
           bits[3:0] trigger type and level flags.  
                   1 = low-to-high edge triggered  
                   2 = high-to-low edge triggered  
                   4 = active high level-sensitive  
                   8 = active low level-sensitive  

    - ==补充== 中断划分

    中断按来源分类:

    • 外部中断
    • 内部中断

    按可屏蔽:

    • 可屏蔽中断
    • 不可屏蔽中断

    按入口地址:

    • 向量中断(硬件提供入口地址)
    • 非向量中断(软件提供入口地址)

    ARM平台支持GIC中断控制器:

    • GIC所支持的中断类型:

      • 1.PPI:私有中断,中断必须绑定一个固定CPU核,当处理该中断时,必须由绑定的CPU核处理
      • 2.SPI:共享中断,中断的处理可被任意的CPU核处理
      • 3.SWI:软中断,用于处理核间通信和调度。

    内核 –|- cpu —– GIC———中断控制器 ……..—|—外设
    ————————————————-
    soc内部

    - gpio

    gpio也是最常见的IO口,常用的属性有

    • “gpio-controller”,用来说明该节点描述的是一个gpio控制器
    • “#gpio-cells”,用来描述gpio使用节点的属性一个cell的内容,即 `属性 = <&引用GPIO节点别名 GPIO标号 工作模式>
    led@4{
        compatible = "xj4421, key";
        gpx2_7 = <&gpx2 7 0>;
    }
    展开全文
  • Linux设备树相关操作

    2019-10-30 19:50:25
    Linux设备树相关操作以及驱动开发流程简介相关文件组成和介绍dts和bingings设备树文件之间的关系官方文档设备树dts的基本构造节点和根节点 简介 最近在学习设备树以及设备基于设备树的驱动开发,其实我是一直在纠结...

    简介

    最近在学习设备树以及设备基于设备树的驱动开发,其实我是一直在纠结要不要写这篇博客的,因为自己了解的仅仅是设备树的一些定义,一些操作,还没有去看源码,这样写出来的博客并不是太有深度的,但是还是想记录一下自己的学习历程,对自己这一周多的学习大概做一些输出,所以还是写了这篇博客,讲解一下Linux设备树的一些相关操作以及基于设备树的驱动开发流程。
    设备树的引入主要是为了减少重用率低的代码,随着Linux内核以及ARM的发展,arch/arm文件夹的规模是日益庞大,同时里面的代码大部分是芯片厂商对自己的芯片描述和板卡厂商对自己产品的板级描述,一大堆xx-mach文件,这样的文件是难以复用的,它们各自实现了IO操作以及板级的控制,为了改变这样的局面引入了设备树机制,设备树机制最先是PowerPC引入了,设备树用一个树状结构来描述了支持体系,一款芯片可以看做是一个树干,基于它所开发的板卡可以看做是树枝,他们有共同的部分,也有板级的区别,同时也引入了pinctrl子系统改进了GPIO子系统,全部基于设备树,这样内核的代码复用率大大提高,同时也大大降低了驱动的移植难度,很多的驱动仅仅只需要修改设备树即可完成驱动的移植,所以设备树的加入虽然略微提高了学习成本但是带来的回报也是丰厚的。

    相关文件组成和介绍

    dts和bingings

    文件分为dts和bingings
    bindings包含设备树用到的所有宏定义,都放到bindings目录下
    dts分为dts和dtsi文件,dts是板级文件,dtsi是“平台文件”,另外还有使用文档在Documentation/devicetree
    .dts描述板级信息(有哪些IIC设备、SPI设备等)
    .dtsi描述SOC级信息
    DTS是设备树源码文件
    DTB是将DTS编译后得到的二进制文件
    将.dts编译为.dtb需要DTC文件 工具源码在scripts/dtc目录下
    在源码文件夹中执行make dtbs就可以进行设备树的编译
    4412开发板的设备树文件:arch/arm/boot/dts/exynos4412-itop-elite.dts
    这里的平台文件是指支持的不止一块板子而是一类板子

    设备树文件之间的关系

    dts文件包含的头文件

    #include <dt-bindings/sound/samsung-i2s.h>
    #include <dt-bindings/pwm/pwm.h>
    #include <dt-bindings/gpio/gpio.h>
    #include <dt-bindings/input/input.h>
    
    #include "exynos4412-itop-scp-core.dtsi"
    

    dtsi文件

    ----dt-bindings/clock/exynos4.h
    ----dt-bindings/clock/exynos-audss-clk.h
    ----dt-bindings/interrupt-controller/arm-gic.h
    ----dt-bindings/interrupt-controller/irq.h
    ----exynos-syscon-restart.dtsi
    --exynos4412-pinctrl.dtsi
    ----dt-bindings/pinctrl/samsung.h
    --exynos4-cpu-thermal.dtsi
    ----include <dt-bindings/thermal/thermal.h>
    

    官方文档

    设备树的文档资料十分详尽,基本上看着文档就可以进行配置,设备树文档对每一个需要配置的地方都有详细的解释以及示例
    比如下面两个文档
    Documentation/devicetree/usage-model.txt
    Documentation/devicetree/bindings/gpio/gpio-samsung.txt

    设备树dts的基本构造

    节点和根节点

    {}框起来的,称为节点
    /{}在dts的最开头,称为根节点

    节点的标准结构是xxx@yyy{ … }
    xxx是节点的名字,yyy则不是必须的,其值为节点的地址(寄存器地址或其他地址)
    label:node-name@unit-address
    引入label的目的是为了方便访问节点,可以直接通过&label来访问这个节点
    支持几种数据形式:

    • 字符串
    • 32位无符号整数
    • 字符串列表

    节点可以包含属性和子节点

    属性

    设备树学习的主要部分:设备树文件中的属性的配置,驱动文件中调用设备树中的属性

    • compatible
      类似设备名称,兼容性属性,字符串列表,用于将设备和驱动绑定起来
      格式:“manufacturer,model”
      其中manufacturer表示厂商,model一般是模块对应的驱动名字
      一般的驱动程序文件都会有一个OF匹配表,此OF匹配表保存着一些compatible值,如果设备节点的compatible属性值和OF匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动
    • model
      字符串
      描述设备模块信息,比如名字
    • status
      字符串,设备的状态
      okey:可操作
      disable:当前不可操作,但是在未来可以变为可操作,如热插拔设备插入后
      fail:不可操作,检测到了一系列错误,也不大可能变得可操作
      fail-sss:同fail,后面的sss部分是检测到的错误内容
    • #address-cells和#size-cells
      都是无符号32位整型,可以用在任何拥有子节点的设备中
      用于描述子节点的地址信息
      #address-cells决定子节点reg属性地址信息所占用的字长(32位)
      #size-cells决定了子节点reg属性中长度信息所占用的字长(32位)
      一般这两个都是1
      这两个属性表明了子节点应该如何编写reg属性值。一般reg属性都是和地址相关的内容
      reg=<address1 length1 address2 length2 address3 length3……>
    • reg
      用于描述设备地址空间资源信息
      一般都是某个外设的寄存器地址范围信息
    • ranges
      可以为空或者按照(child-bus-address,parent-bus-address,length)格式编写的数字矩阵
      是一个地址映射/转移表,每个项目由字地址、父地址和地址空间长度三部分组成
      child-bus-address:子总线地址空间的物理地址,由父节点的#address-cells确定所占用字长
      parent-bus-address:父总线空间的物理地址,同样由父节点的#address-cells确定所占用字长
      length:子地址空间的长度,由父节点的#size-cells确定所占用字长
    • name
      字符串,记录节点名字,已被启用不推荐
    • device_type
      字符串,IEEE 1275会用到此属性,用于描述设备的FCode,设备树没有FCode,被弃用
      只能用于cpu节点或者memory节点
    • label—标签
    • gpios—IO
    • pwms—PWM

    在设备树上添加节点

    在.dts文件中添加

    设备树在系统中的体现

    /proc/device-tree/ 目录下是根据节点名字创建的不同文件夹
    就是将设备树分级存储
    每个文件夹就是一个节点,里面包含这个节点的属性以及它所包含的子节点

    特殊子节点

    • aliases子节点
      别名 &label
    • chosen子节点
      不是一个真正的设备,主要是为了uboot向linux内核传递数据
      重点是bootargs
      stdout-path 设置debug串口
      uboot会将bootargs填入chosen节点
      在这里插入图片描述

    内核如何识别设备树

    匹配方式

    使用设备树之前:
    uboot传递machine id,MACHINE_START、MACHINE_END
    使用设备树之后:
    machine_desc
    DT_MACHINE_START、DT_MACHINE_END
    machine_desc结构体的.dt_compat成员变量保存着本设备兼容属性
    Linux内核调用start_kernel函数来启动内核
    会调用setup_arch函数来匹配machine_desc
    setup_arch中调用setup_machine_fdt来获取machine_desc,其参数是uboot传递给linux内核的dtb文件首地址,返回值是最匹配的machine_desc
    在这里插入图片描述

    内核解析DTB文件

    Linux内核会在启动的时候解析DTB文件,然后在/proc/device-tree目录下生成相应的设备树节点文件
    在这里插入图片描述

    设备树常用OF操作函数

    of是open firmware的缩写,是定义计算机固件系统接口的标准,以前由电气和电子工程师协会认可。它起源于Sun,已被Sun,Apple,IBM,ARM和大多数其他非x86 PCI芯片组供应商使用。
    ARM的设备树操作就遵守open firmware标准
    OF操作函数是编写驱动的时获取设备树信息调用的函数
    定义在include/linux/of.h文件中

    查找节点的OF函数

    linux内核使用device_node结构体来描述一个节点

    struct device_node {
    	const char *name;
    	const char *type;
    	phandle phandle;
    	const char *full_name;
    	struct fwnode_handle fwnode;
    
    	struct	property *properties;
    	struct	property *deadprops;	/* removed properties */
    	struct	device_node *parent;
    	struct	device_node *child;
    	struct	device_node *sibling;
    	struct	kobject kobj;
    	unsigned long _flags;
    	void	*data;
    #if defined(CONFIG_SPARC)
    	const char *path_component_name;
    	unsigned int unique_id;
    	struct of_irq_controller *irq_trans;
    #endif
    }
    
    • 1、of_find_node_by_name
      通过子节点名字查找子节点
    • 2、of_find_node_by_type
      通过子节点类型查找子节点,device_type
    • 3、of_find_compatible_node
      根据device_type和compatible查找子节点,device_type可以设置为NULL
    • 4、of_find_matching_node_and_match
      通过of_device_id匹配表来查找指定的节点
    • 5、of_find_node_by_path
      通过路径来查找指定节点

    查找父/子节点的OF函数

    • 1、of_get_parent
      父节点
    • 2、of_get_next_child
      迭代的查找子节点

    提取属性值

    节点的属性信息里面保存了驱动所需要的内容,因此对于属性值的提取非常重要, Linux内核中使用结构体 property表示属性,此结构体同样定义在文件 include/linux/of.h中,内容如下:

    struct property { char *name; /* 属性名字 */
    			int length; /* 属性长度 */ 
    			void *value; /* 属性值 */ 
    			struct property *next; /* 下一个属性 */ 
    			unsigned long _flags; 
    			unsigned int unique_id; 
    			struct bin_attribute attr; 
    			};
    
    • 1 、of_find_property
      用于查找指定的属性,函数原型如下:
    struct property *of_find_property(const struct device_node *np,
    					 const char *name,
    					 int *lenp);
    
    • 2、of_property_count_elems_of_size
      函数用于获取属性中元素的数量,比如 reg属性值是一个数组,那么使用此函数可以获取到这个数组的大小,此函数原型如下:
    int of_property_count_elems_of_size(const struct device_node *np,
    				const char *propname, int elem_size);
    
    • 3、of_property_read_u32_index
      函数用于从属性中获取指定标号的 u32类型数据值 (无符号 32位 ),比如某个属性有多个 u32类型的值,那么就可以使用此函数来获取指定标号的数据值,原型如下:
    int of_property_read_u32_index(const struct device_node *np,
    				       const char *propname,
    				       u32 index, u32 *out_value);
    
    • 4、读取数组数据的函数
      of_property_read_u8_array
      of_property_read_u16_array
      of_property_read_u32_array
      of_property_read_u64_array
      这 4个函数分别是读取属性中 u8、 u16、 u32和 u64类型的数组数据,比如大多数的 reg属性都是数组数据,可以使用这 4个函数一次读取出 reg属性中的所有数据。
    • 5 、读取整形值属性的函数
      of_property_read_u8
      of_property_read_u16
      of_property_read_u32
      of_property_read_u64
    • 6、of_property_read_string
      用于读取属性中字符串值,函数原型如下:
    int of_property_read_string(const struct device_node *np,
    				   const char *propname,
    				   const char **out_string);
    
    • 7、of_n_addr_cells
      函数用于获取 #address-cells属性值,函数原型如下:
    int of_n_addr_cells(struct device_node *np);
    
    • 8、 of_n_size_cells
      函数用于获取 #size-cells属性值,函数原型如下:
    int of_n_size_cells(struct device_node *np) 函数
    

    其他常用的OF函数

    • 1、of_device_is_compatible
      函数用于查看节点的 compatible属性是否有包含 compat指定的字符串,也就是检查设备节点的兼容性,函数原型如下:
    int of_device_is_compatible(const struct device_node *device,
    				   const char *);
    
    • 2、of_get_address
      函数用于获取地址相关属性,主要是“ reg”或者 assigned-addresses”属性值,函数属性如下:
    const __be32 *of_get_address(struct device_node *dev, int index, u64 *size, unsigned int *flags);
    
    • 3、of_translate_address
      函数负责将从设备树读取到的地址转换为物理地址,函数原型如下:
    u64 of_translate_address(struct device_node *dev,const __be32 *in_addr)
    
    • 4、of_address_to_resource
      IIC、 SPI、 GPIO等这些外设都有对应的寄存器,这些寄存器其实就是一组内存空间, Linux内核使用 resource结构体来描述一段内存空间,“ resource”翻译出来就是“资源”,因此用 resource结构体描述的都是设备资源信息, resource结构体定义在文件 include/linux/ioport.h中,定义如下:
    struct resource {resource_size_t start; 
    				resource_size_t end; 
    				const char *name; 
    				unsigned long flags; 
    				struct resource *parent, *sibling, *child; 
    				};
    

    对于 32位的 SOC来说, resource_size_t是 u32类型的。其中 start表示开始地址, end表示结束地址, name是这个资源的名字, flags是资源标志位,一般表示资源类型,可选的资源标志定义在文件 include/linux/ioport.h中,如下所示:

    #define IORESOURCE_BITS		0x000000ff	/* Bus-specific bits */
    
    #define IORESOURCE_TYPE_BITS	0x00001f00	/* Resource type */
    #define IORESOURCE_IO		0x00000100	/* PCI/ISA I/O ports */
    #define IORESOURCE_MEM		0x00000200
    #define IORESOURCE_REG		0x00000300	/* Register offsets */
    #define IORESOURCE_IRQ		0x00000400
    #define IORESOURCE_DMA		0x00000800
    #define IORESOURCE_BUS		0x00001000
    
    #define IORESOURCE_PREFETCH	0x00002000	/* No side effects */
    #define IORESOURCE_READONLY	0x00004000
    #define IORESOURCE_CACHEABLE	0x00008000
    #define IORESOURCE_RANGELENGTH	0x00010000
    #define IORESOURCE_SHADOWABLE	0x00020000
    
    #define IORESOURCE_SIZEALIGN	0x00040000	/* size indicates alignment */
    #define IORESOURCE_STARTALIGN	0x00080000	/* start field is alignment */
    
    #define IORESOURCE_MEM_64	0x00100000
    #define IORESOURCE_WINDOW	0x00200000	/* forwarded by bridge */
    #define IORESOURCE_MUXED	0x00400000	/* Resource is software muxed */
    
    #define IORESOURCE_EXT_TYPE_BITS 0x01000000	/* Resource extended types */
    #define IORESOURCE_SYSRAM	0x01000000	/* System RAM (modifier) */
    
    #define IORESOURCE_EXCLUSIVE	0x08000000	/* Userland may not map this resource */
    
    #define IORESOURCE_DISABLED	0x10000000
    #define IORESOURCE_UNSET	0x20000000	/* No address assigned yet */
    #define IORESOURCE_AUTO		0x40000000
    #define IORESOURCE_BUSY		0x80000000	/* Driver has marked this resource busy */
    

    一般最常见的资源标志是IORESOURCE_MEM、IORESOURCE_REG和IORESOURCE_IRQ等
    of_address_to_resource函数是从设备树中提取资源值,本质上就是取reg属性值然后将其转换为resource结构体类型,原型如下:

    int of_address_to_resource(struct device_node *dev, int index, struct resource *r)
    
    • 5、of_iomap
      函数用于直接内存映射,以前我们会通过 ioremap函数来完成物理地址到虚拟地址的映射,采用设备树以后就可以直接通过 of_iomap函数来获取内存地址所对应的虚拟地址,不需要使用 ioremap函数了。
      当然ioremap函数也是可以使用的,只是在采用了设备树后,大部分的驱动都使用了of_iomap函数
      函数原型如下:
      void __iomem *of_iomap(struct device_node *np, int index)

    总结

    这个博客讲解的都是设备树很表面的东西,它的由来、语法以及驱动中如何进行调用,后面如果自己了解深入了也会对设备树关键部分的代码进行分析。
    我们可以总结设备树的一些套路
    三个主要目标:
    1、platform identification,平台描述
    2、runtime configuration,运行环境配置
    3、device population.描述所有设备

    • platform identification
      compatible = “ti,omap3-beagleboard”, “ti,omap3450”, “ti,omap3”;
      compatible = “ti,omap3-beagleboard-xm”, “ti,omap3450”, “ti,omap3”;
      可以知道这是TI omap3平台,omap3450芯片,omap3-beagleboard开发板
      compatible = “topeet,itop4412-elite”, “samsung,exynos4412”, “samsung,exynos4”;
    • runtime configuration
      大多通过chosen节点
      例如:
      chosen { bootargs = “console=ttyS0,115200 loglevel=8”;
      initrd-start = <0xc8000000>;
      initrd-end = <0xc8200000>; };
      4412例子
      chosen {
      bootargs = “root=/dev/mmcblk0p2 rw rootfstype=ext4 rootdelay=1 rootwait”;
      stdout-path = “serial2:115200n8”;
      };
    • device population
      这个就很常见了,设备树其他的就是做这个的

    理解它的主要目标以及使用方法我们先熟练的使用然后再去研究它的核心。

    展开全文
  • Linux 设备树详解

    千次阅读 2018-11-07 15:37:44
    本文基于天嵌E9V3开发板,详解设备树的语法结构和用法。 一、设备树 二、E9V3设备树总览 E9V3设备树总览: 三、设备树编写规则

    本文基于天嵌E9V3开发板,详解设备树的规则和用法。

    一、基本概念

    DTS即Device Tree Source,是一个文本形式的文件,用于描述硬件信息,包括CPU的数量和类别、内存基地址和大小、中断控制器、总线和桥、外设、时钟和GPIO控制器等。
    DTB即Device Tree Blob,是一个二进制形式的文件,由linux内核识别,为其中的设备匹配合适的驱动程序。
    DTC即Device Tree Compiler,将适合人类阅读和编辑的DTS文件编译成适合机器处理的DTB文件。
    编译内核的时候会同时使用DTC 将DTS编译成DTB,天嵌E9V3使用的DTS文件e9v3-sabresd.dts位于/arch/arm/boot/dts目录下。
    在这里插入图片描述
    如上图所示,bootloader读取dtb文件放入RAM中,并将存放地址告诉linux内核,内核启动以后从该地址读取相应的设备信息,匹配平台和设备驱动。

    二、E9V3设备树总览

    linux中的一个dts文件对应一个machine, 不同的machine可能使用相同的SOC,只是对外设的使用不同,这些不同的dts文件势必包含很多相同的内容,为了简化,可以把公用的部分提炼为dtsi文件。
    e9v3-sabresd.dts包含dtsi的结构如下:
    在这里插入图片描述

    列出各个文件中的节点,如下图所示,是不是有点像有很多分支的树?
    在这里插入图片描述

    三、设备树编写规则

    Device Tree的编写规则可参考文档<<devicetree-specification-v0.2.pdf>>, 以下简称spec,下载链接为:
    https://github.com/devicetree-org/devicetree-specification/releases/tag/v0.2

    设备树由一个一个的节点组成,每个设备树有且仅有一个根节点,节点可以包含子节点。

    1、节点名称
    基本的节点名格式如下:
    node-name@unit-address
    其中node-name由字母、数字和一些特殊字符构成的字符串,长度不超过31个字符,可自定义,但为了可读性,spec中规定了一些约定成熟的名称,比如cpus, memory, bus,clock等。
    unit-address为节点的地址,通常为寄存器的首地址,比如imx6q datasheet中uart1的寄存器地址范围为0202_0000~0202_3FFF,在定义uart1节点时,对应的unit-address为0202_0000:
    uart1: serial@02020000 {

    }
    有些节点没有对应的寄存器,则unit-address可省略,节点名只由node-name组成,比如cpus:
    cpus {

    }
    根节点的名称比较特殊,由一个斜杠组成:
    /{

    }

    2、label标签

    三、设备与驱动的匹配

    linux内核启动以后,先解析并注册dts中的设备,然后再注册驱动,比较驱动中的compatible 属性和设备中的compatible 属性,或者比较两者的name属性,如果一致则匹配成功。
    1、解析dtb
    在start_kernel() --> setup_arch(0 --> unflatten_device_tree() --> __unflatten_device_tree()函数中扫描dtb,并转换成节点是device_node的树状结构。
    注:代码基于linux4.1.15内核(下同)

    static void __unflatten_device_tree()
    {
        ...
    	/* First pass, scan for size */
    	start = 0;
    	size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0, true);
    	size = ALIGN(size, 4);
        ...
    	/* Second pass, do actual unflattening */
    	start = 0;
    	unflatten_dt_node(blob, mem, &start, NULL, mynodes, 0, false);
       ...
    }
    

    2. 注册dts设备

    imx6q_init_machine() --> of_platform_populate()。
    在of_platform_populate()中循环扫描根节点下的各节点:

    int of_platform_populate()
    {
        ...
    	for_each_child_of_node(root, child) {
    		rc = of_platform_bus_create(child, matches, lookup, parent, true);
         }
         ...
    }
    
    static int of_platform_bus_create()
    {
        ...
    	/* Make sure it has a compatible property */
    	if (strict && (!of_get_property(bus, "compatible", NULL))) {
    		pr_debug("%s() - skipping %s, no compatible prop\n",
    			 __func__, bus->full_name);
    		return 0;
    	}
    
    	auxdata = of_dev_lookup(lookup, bus);
    	if (auxdata) {
    		bus_id = auxdata->name;
    		platform_data = auxdata->platform_data;
    	}
        ...
    	dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
    	if (!dev || !of_match_node(matches, bus))
    		return 0;
        如果节点有子节点,则递归调用of_platform_bus_create()扫描节点的子节点:
    	for_each_child_of_node(bus, child) {
    		pr_debug("   create child: %s\n", child->full_name);
    		rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
    		if (rc) {
    			of_node_put(child);
    			break;
    		}
    	}
    	of_node_set_flag(bus, OF_POPULATED_BUS);
    	return rc;
    }
    

    最终调用of_platform_device_create_pdata() —> of_device_add() 注册设备并添加到对应的链表中。

    3、注册驱动
    Linux注册驱动的函数为driver_register(),或者其包装函数如platform_driver_register(),而driver_register()或者其包装函数一般在驱动的初始化函数xxx_init()中调用。
    驱动初始化函数xxx_init()被调用的路劲为:
    start_kernel() --> rest_init() --> Kernel_init() --> kernel_init_freeable() --> do_basic_setup() --> do_initcalls:
    在这里插入图片描述

    简而言之,在start_kernel()中调用driver_register()注册驱动程序。

    4、匹配设备
    追踪driver_register()函数,driver_register() --> bus_add_driver() --> driver_attach() --> __driver_attach:

    static int __driver_attach(struct device *dev, void *data)
    {
    	struct device_driver *drv = data;
    	if (!driver_match_device(drv, dev))
    		return 0;
    
    	if (dev->parent)	/* Needed for USB */
    		device_lock(dev->parent);
    	device_lock(dev);
    	if (!dev->driver)
    		driver_probe_device(drv, dev);
    	device_unlock(dev);
    	if (dev->parent)
    		device_unlock(dev->parent);
    	return 0;
    }
    

    driver_match_device()中寻找匹配的设备,如果匹配成功则执行驱动的probe函数。
    driver_match_device()最终会调用平台的匹配函数platform_match():

    static int platform_match(struct device *dev, struct device_driver *drv)
    {
    	struct platform_device *pdev = to_platform_device(dev);
    	struct platform_driver *pdrv = to_platform_driver(drv);
    
    	/* When driver_override is set, only bind to the matching driver */
    	if (pdev->driver_override)
    		return !strcmp(pdev->driver_override, drv->name);
    
    	/* Attempt an OF style match first */
    	if (of_driver_match_device(dev, drv))
    		return 1;
    
    	/* Then try ACPI style match */
    	if (acpi_driver_match_device(dev, drv))
    		return 1;
    
    	/* Then try to match against the id table */
    	if (pdrv->id_table)
    		return platform_match_id(pdrv->id_table, pdev) != NULL;
    
    	/* fall-back to driver name match */
    	return (strcmp(pdev->name, drv->name) == 0);
    }
    

    从代码中可以看出, platform_match()会采用多种方法进行匹配:

    1. of_driver_match_device将根据驱动程序of_match_table中的compatible属性,与设备中的compatible属性进行比对。
    2. 其次调用acpi_driver_match_device()进行匹配。
    3. 如果前2种方法都没有匹配的,最后比对设备和驱动的name字符串是否一致。

    以GPIO-key为例,设备和驱动匹配示意图如下:
    在这里插入图片描述

    展开全文
  • Linux 设备树添加spi设备

    千次阅读 2018-12-16 22:38:38
    Linux:4.6 应用开发板:zynq系列 zc706、zedboard 文件系统:ubuntu12 参考帖子:...之前实验过spi控制器下面挂载spi设备,当时,关于spi设备树的节点描述如下...
  • Linux 设备树

    2020-07-17 10:17:25
    43.1 什么是设备树设备树(Device Tree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做 DTS(Device Tree Source),这个 DTS 文件采用树形...在没有设备树的时候 Linux 是如何描述 ARM 架构中的板级信息呢
  • Linux 设备树 DTS 语法

    2020-02-15 18:37:00
    设备树(Device Tree) DTS(Device Tree Source) : 描述设备树的文件 DTS文件采用 树形结构描述板级设备 如:CPU数目,内存基地址,IIC接口的设备,SPI接口的设备 树干:系统总线 树支:IIC控制器,GPIO...
  • linux设备树笔记

    2017-06-06 11:26:54
    linux设备树笔记 网址:http://www.360doc.com/content/15/1113/11/15700426_512794532.shtml linux设备树笔记__dts基本概念及语法 0条评论 设备树手册...
  • 设备树简介   在内核源码中,存在大量对板级细节信息描述的代码。这些代码充斥在/arch/arm/plat-xxx和/arch/arm/mach-xxx目录,对内核而言这些platform设备、resource、i2c_board_info、spi_board_info以及各种...
  • arm linux设备树

    2020-10-23 16:07:24
    文章目录设备树概述设备树的特点设备树的使用编译设备树内核如何加载dtb 设备树概述 在linux2.6以前,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量重复的、用于描述设备细节的代码。导致内核代码迅速膨胀,...
  •     设备树是一种描述硬件的数据结构,它起源于OpenFirmware(OF)。在Linux 2.6中, ARM架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx和arch/arm/...1. linux设备树中DTS、 DTC和DTB的关系 (1) DTS: ....
  • linux设备树简析

    2020-08-24 10:07:59
    1.什么是设备树 设备树(Device Tree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做 DTS(Device Tree Source),这个 DTS 文件采用树形结构描述板级设备,也就是开发板上的设备信息,比如CPU 数量、 内存...
  • Linux设备树的初步接触 1. 编译设备树 # 在Linux kernel的源目录下: make make ARCH=arm CROSS_COMPILE=arm-xxxxx-linux- dtbs 2. 反编译设备树 # 在Linux kernel的源目录下(在其他目录也行): scripts/dtc/dtc -I ...
  • 文章目录前言设备树DTS语法内容标准属性向节点追加或修改内容设备树在目录中的体现Linux 内核解析 DTB 文件帮助文档信息设备树节点的操作函数1、查找节点的 of 函数2、查找父/子节点的 OF 函数3、提取属性值的 OF ...
  • Linux 设备树的使用技巧

    千次阅读 2017-05-21 16:32:55
    Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。引入了设备树之后,驱动代码只负责处理...
  • linux设备树

    千次阅读 2017-08-19 19:09:19
    设备树的最终目的 提供一种语言来解析硬件配置信息   设备端:使用设备树之前 硬件的描述信息,放置在一个个arch/xxx/mach-xxx/board-xxx.c的C文件中 static struct resource dm9000_resource1[] ={ { ...
  • Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。 引入了设备树之后,驱动代码只负责处理...
  • 设备树(Device Tree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做 DTS(Device Tree Source),这个 DTS 文件采用树形结构描述板级设备,也就是开发板上的设备信息,比如 CPU 数量、 内存基地址、IIC ...
  • 1、设备树格式 设备树节点的node格式 [label:] node-name[@unit-address] { [properties definitions] [child nodes] }; 例子: 1150 fusb0: fusb30x@22 { 1151 compatible = "fairchild,fusb302"; 1152 reg ...
  • linux 设备树详解

    2018-03-16 17:18:37
    转载:https://www.cnblogs.com/xiaojiang1025/p/6131381.html概念Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备...
  • linux设备树启动

    千次阅读 2017-09-03 11:34:32
    在早期的arm linux内核中,板级的细节信息使用代码的形式,存放在arch/arm目录中,这些板级代码只对相应的开发板有用,却被硬编码进linux内核,显然这不是一种好的方法。Device Tree是一种描述硬件的数据结构,它...
  • 关于Linux 设备树的干货
  • linux设备树使用手册

    千次阅读 2015-10-10 18:00:24
    设备树使用手册 This page walks through how to write a device tree for a new machine. It is intended to provide an overview of device tree concepts and how they are used to describe a machine. ...
  • Linux设备树中一些标准属性介绍标准属性1、compatible 属性2、 model 属性3、 status 属性4、 #address-cells 和#size-cells 属性5、 reg 属性6、 ranges 属性7、 name 属性8、 device_type 属性 标准属性 节点是由...
  • 一般情况下,我们不会从头编写一个完整的dts文件,SOC厂商一般会直接提供一个有着基本框架的dts文件,当需要添加自己的板子设备树文件时,基于厂商提供的dts文件修改即可。所以我们要了解dts设备树文件的语法,这样...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,320
精华内容 3,728
关键字:

linux设备树clock

linux 订阅