• Linux 设备树子系统【2】-设备树在platform设备驱动中的使用



    前言

    关与设备树的概念,我们在Exynos4412 内核移植(六)—— 设备树解析 里面已经学习过,下面看一下设备树在设备驱动开发中起到的作用


    Device Tree是一种描述硬件的数据结构,设备树源(Device Tree Source)文件(以.dts结尾)就是用来描述目标板硬件信息的。Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的namevalue。在Device Tree中,可描述的信息包括(原先这些信息大多被hard codekernel中)

    一、Device Tree基本数据格式

    device tree 是一个简单的节点属性树,属性是键值对,节点可以包含属性子节点。下面是一个.dts 格式的简单设备树。

    /{
    	node1 {
    		a-string-property = "A string";
    		a-string-list-property = "first string","second string";
    		a-byte-data-property = [0x01 0x23 0x34 0x56];
    		child-node1 {
    			first-child-property;
    			seconde-child-property = <1>;
    			a-string-property = "Hello, world";
    		};
    		chilid-node2{
    		};
    	};
    	node2 {
    		an-empty-property;
    		a-cell-property = <1 2 3 4>;/*each number(cell) is a uint32*/
    		child-node1{
    		};
    	};
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    该树并未描述任何东西,也不具备任何实际意义,但它却揭示了节点和属性的结构。即:

    1. 一个的根节点:'/',两个子节点:node1和node2node1的子节点:child-node1child-node2,一些属性分散在树之间。
    2. 属性是一些简单的键值对key-value pairs)value可以为空也可以包含任意的字节流。而数据类型并没有编码成数据结构,有一些基本数据表示可以在device tree源文件中表示。
    3. 文本字符串(null 终止)用双引号来表示:string-property = "a string"
    4. “Cells”是由尖括号分隔的32位无符号整数:cell-property = <0xbeef 123 0xabcd1234>
    5. 二进制数据是用方括号分隔:binary-property = [0x01 0x23 0x45 0x67];
    6. 不同格式的数据可以用逗号连接在一起:mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
    7. 逗号也可以用来创建字符串列表:string-list = "red fish", "blue fish";

    二、设备在device tree 中的描述

    系统中的每个设备由 device tree 的一个节点来表示

    2.1 节点命名

    每个节点都必须有一个[@]格式的名称。是一个简单的ascii字符串,最长为31个字符,总的来说,节点命名是根据它代表什么设备。比如说,一个代表3com以太网适配器的节点应该命名为ethernet,而不是3com509

    如果节点描述的设备有地址的话,就应该加上unit-address,unit-address通常是用来访问设备的主地址,并在节点的reg属性中被列出。后面我们将谈到reg属性

    2.2 设备

    /{
    	compatible = "acme,coyotes-revenge";
    	cpus {
    		cpu@0 {
    			compatible = "arm,cortex-a9";
    		};
    		cpu@1 {
    			compatible = "arm,cortex-a9";
    		};
    	};
    	serial@101F0000 {
    		compatible = "arm,pl011";
    	};
    	serial@101F2000 {
    		compatible = "arm,pl011";
    	};
    	gpio@101F3000 {
    		compatible = "arm,pl061";
    	};
    	interrupt-cotroller@10140000 {
    		compatible = "arm,pl190";
    	};
    		spi@10115000 {
    		compatible = "arm,pl022";
    	};
    	
    	external-bus {
    		ethernet@0,0 {
    			compatible = "smc,smc91c111";
    		};
    		i2c@1,0 {
    			compatible = "acme,a1234-i2c-bus";
    			rtc@58 {
    				compatible = "maxim,ds1338";
    			};
            };
    		flash@2,0 {
    			compatible = "samsung,k8f1315ebm", "cfi-flash";
           	};
       	 };
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在上面的设备树中,系统中的设备节点已经添加进来,树的层次结构反映了设备如何连到系统中。外部总线上的设备就是外部总线节点的子节点,i2c设备是i2c总线控制节点的子节点。总的来说,层次结构表现的是从CPU视角来看的系统视图。在这里这棵树是依然是无效的。它缺少关于设备之间的连接信息。稍后将添加这些数据。

    设备树中应当注意:每个设备节点有一个compatible属性。flash节点的compatible属性有两个字符串。请阅读下一节以了解更多内容。 之前提到的,节点命名应当反映设备的类型,而不是特定型号。请参考ePAPR规范2.2.2节的通用节点命名,应优先使用这些命名。

    2.3 compatible 属性

    树中的每一个代表了一个设备的节点都要有一个compatible属性。compatible是 OS 用来决定绑定到设备的设备驱动的关键。

    compatible是字符串的列表。列表中的第一个字符串指定了","格式的节点代表的确切设备,第二个字符串代表了与该设备兼容的其他设备。例如,Freescale MPC8349 SoC有一个串口设备实现了National Semiconductor ns16550寄存器接口。因此MPC8349串口设备的compatible属性为:compatible = "fsl,mpc8349-uart", "ns16550"。在这里,fsl,mpc8349-uart指定了确切的设备,ns16550表明它与National Semiconductor 16550 UART是寄存器级兼容的。

    2.4 编址

    可编址的设备使用下列属性来将地址信息编码进设备树
    #address-cells; #size-cells; #reg;
    每个可寻址的设备有一个reg属性,即以下面形式表示的元组列表:
    reg =
    每个元组,。每个地址值由一个或多个32位整数列表组成,被称做cells。同样地,长度值可以是cells列表,也可以为空。

    既然addresslength字段是大小可变的变量,父节点的#address-cells#size-cells属性用来说明各个子节点有多少个cells。换句话说,正确解释一个子节点的reg属性需要父节点的#address-cells#size-cells值。

    2.5 内存映射设备

    CPU节点中的单一地址值不同,内存映射设备会被分配一个它能响应的地址范围。#size-cells用来说明每个子节点中reg元组的长度大小

    在下面的示例中,每个地址值是1 cell (32位) ,并且每个的长度值也为1 cell,这在32位系统中是非常典型的。64位计算机可以在设备树中使用2作为#address-cells#size-cells的值来实现64位寻址。

    serial@101f2000 {
    	compatible = "arm,pl011";
    	reg = <0x101f2000 0x1000>;
    };
    gpio@101f3000 {
    	compatible = "arm,pl061";
    	reg = <0x101f3000 0x1000
    		   0x101f4000 0x0010>;
    };
    
    interrupt-controller@10140000 {
    	compatible = "arm,pl190";
    	reg = <0x1014000 0x1000>;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    每个设备都被分配了一个基地址及该区域大小。本例中的GPIO设备地址被分成两个地址范围:0x101f3000~0x101f3fff0x101f4000~0x101f400f

    三、设备树在platform设备驱动开发中的使用解析

    我们仍以 Linux 设备驱动开发 —— platform设备驱动应用实例解析 文中的例子来解析设备树在platform设备驱动中如何使用;

    3.1 设备树对platform中platform_device的替换

    其实我们可以看到,Device Tree 是用来描述设备信息的,每一个设备在设备树中是以节点的形式表现出来;而在上面的 platform 设备中,我们利用platform_device 来描述一个设备,我们可以看一下二者的对比

    fs4412-beep{
             compatible = "fs4412,beep";
             reg = < 0x114000a0 0x4  0x139D0000 0x14 >;
    };
    
    a -- fs4412-beep 为节点名,符合咱们前面提到的节点命名规范;
          我们通过名字可以知道,该节点描述的设备是beep, 设备名是fs4412-beep;
    
    b -- compatible = "fs4412,beep"; compatible 属性, 即一个字符串;
          前面提到, 所有新的compatible值都应使用制造商的前缀,这里是
    fs4412;
    
    c --  reg = < 0x114000a0 0x4  0x139D0000 0x14 >;
           reg属性来将地址信息编码进设备树,表示该设备的地址范围;这里是我们用到的寄存器及偏移量;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    	static struct resource beep_resource[] = 
    	{
    		[0] = {
    			.start = 0x114000a0,
    			.end = 0x114000a0+0x4,
    			.flag = IORESOURCE_MEM,
    		},
    		[1] = {
    			.start = 0x139D0000,
    			.end = 0x139D0000+0x14,
    			 .flags = IORESOURCE_MEM,
    		},
    	};
    	static struct platform_device hello_device = 
    	{
    		.name = "bigbang",/*没用了*/
    		.id = -1;
    		.dev.release = hello_release,
    		.num_resources = ARRAY_SIZE(beep_resource),
    		.resosource = beep_resource,
    	};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    参考

    Linux 设备驱动开发 —— 设备树在platform设备驱动中的使用

  • 相关阅读:
    mysql索引失效的几种情况
    单线双线多线服务器有哪些区别
    人工智能第2版学习——博弈中的搜索1
    [面试直通版]操作系统核心之存储系统(下)
    NLP:生成熟悉NLP开源工具,如NLTK、 HanLP等,并搜寻、下载和熟悉PKU、 CoreNLP, LTP MSR, AS CITYI 等语料库。
    Logback 配置文件这样优化,TPS提高 10 倍
    本文是对优雅草蜻蜓C影视便捷追剧小程序微信支付配置教程-大部分小程序支付通用,从微信配置到后台的详解,其他小程序系统均可参考
    信号处理与分析-确定性信号的分析
    discuz!论坛开发积分充值插件教程
    FFplay文档解读-14-输入设备二
  • 原文地址:https://blog.csdn.net/m0_46535940/article/details/126267433