设备树的一些知识点

来源:互联网 发布:java agent 做监控 编辑:程序博客网 时间:2024/06/17 13:04

参考网址:http://www.wowotech.net/linux_kenrel/pin-controller-driver.html

可寻址的设备使用如下信息来在Device Tree中编码地址信息:

  •     reg
  •     #address-cells
  •     #size-cells

其中reg的组织形式为reg = <address1 length1 [address2 length2] [address3 length3] ... >,其中的每一组address length表明了设备使用的一个地址范围。address为1个或多个32位的整型(即cell),length表示长度。address 和 length 字段是可变长的,父结点的#address-cells和#size-cells分别决定了子结点reg属性的address和length字段的长度。在本例中:

root结点的#address-cells = <1>;和#size-cells = <1>;决定了serial、gpio、spi等结点的address和length字段的长度分别为1。

cpus 结点的#address-cells = <1>;和#size-cells = <0>;决定了2个cpu子结点的address为1,而length为空,于是形成了2个cpu的reg = <0>;和reg = <1>;

external-bus结点的#address-cells = <2>和#size-cells = <1>;决定了其下的ethernet、i2c、flash的reg字段形如reg = <0 0 0x1000>;、reg = <1 0 0x1000>;和reg = <2 0 0x4000000>;。其中第一个cell(0、1、2)是对应的片选,第2个cell(0,0,0)是相对该片选的基地址,第3个cell(0x1000、0x1000、0x4000000)为length。特别要留意的是i2c结点中定义的 #address-cells = <1>;和#size-cells = <0>;并且作用到了I2C总线上连接的RTC,它的address字段为0x58,是设备的I2C地址。

root结点的子结点描述的是CPU的视图,因此root子结点的address区域就直接位于CPU的memory区域。但是,经过总线桥后的address往往需要经过转换才能对应的CPU的memory映射。external-bus的ranges属性定义了经过external-bus桥后的地址范围如何映射到CPU的memory区域。

[cpp] view plain copy
  1. ranges = <0 0  0x10100000   0x10000     // Chipselect 1, Ethernet    
  2.           1 0  0x10160000   0x10000     // Chipselect 2, i2c controller    
  3.           2 0  0x30000000   0x1000000>; // Chipselect 3, NOR Flash    
ranges是地址转换表,子地址空间的#address-cells为2,父地址空间的#address-cells值为1,因此0 0  0x10100000   0x10000的前2个cell为external-bus片选0上偏移0,第3个cell表示把前面的地址空间映射到CPU的0x10100000位置,第4个cell表示映射的大小为0x10000。


interrupt-controller

interrupt-controller – 这个属性为空,中断控制器应该加上此属性表明自己的身份;
#interrupt-cells – 与#address-cells 和 #size-cells相似,它表明连接此中断控制器的设备的interrupts属性的cell大小。
在整个Device Tree中,与中断相关的属性还包括:
interrupt-parent – 设备结点透过它来指定它所依附的中断控制器的phandle,当结点没有指定interrupt-parent 时,则从父级结点继承。对于本例而言,root结点指定了interrupt-parent = <&intc>;其对应于intc: interrupt-controller@10140000,而root结点的子结点并未指定interrupt-parent,因此它们都继承了intc,即位于0x10140000的中断控制器。

interrupts – 用到了中断的设备结点透过它指定中断号、触发方法等,具体这个属性含有多少个cell,由它依附的中断控制器结点的#interrupt-cells属性决定。而具体每个cell又是什么含义,一般由驱动的实现决定,而且也会在Device Tree的binding文档中说明。譬如,对于ARM GIC中断控制器而言,#interrupt-cells为3,它3个cell的具体含义Documentation/devicetree/bindings/arm/gic.txt就有如下文字说明:

[java] view plain copy
  1. 01   The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI    
  2. 02   interrupts.    
  3. 03    
  4. 04   The 2nd cell contains the interrupt number for the interrupt type.    
  5. 05   SPI interrupts are in the range [0-987].  PPI interrupts are in the    
  6. 06   range [0-15].    
  7. 07    
  8. 08   The 3rd cell is the flags, encoded as follows:    
  9. 09         bits[3:0] trigger type and level flags.    
  10. 10                 1 = low-to-high edge triggered    
  11. 11                 2 = high-to-low edge triggered    
  12. 12                 4 = active high level-sensitive    
  13. 13                 8 = active low level-sensitive    
  14. 14         bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of    
  15. 15         the 8 possible cpus attached to the GIC.  A bit set to '1' indicated    
  16. 16         the interrupt is wired to that CPU.  Only valid for PPI interrupts.    
另外,值得注意的是,一个设备还可能用到多个中断号。对于ARM GIC而言,若某设备使用了SPI的168、169号2个中断,而且都是高电平触发,则该设备结点的interrupts属性可定义为:interrupts = <0 168 4>, <0 169 4>;



一个典型的device tree中的外设node定义如下:

device-node-name {  
        定义该device自己的属性  

        pinctrl-names = "sleep", "default"; 
        pinctrl-0 = ; 
        pinctrl-1 = ;         
    };

下面的伪代码描述了S3C2416 pin controller 的DTS结构:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. pinctrl@56000000 {   
  2.         定义S3C2416 pin controller自己的属性  
  3.   
  4.         定义属于S3C2416 pin controller的pin configurations  
  5.   
  6. }  

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. samsung 24xx系列SOC的pin controller的pin configurations包括两类,一类是定义pin bank,另外一类是定义功能复用配置。  
  2. 第一类如下:  
  3.   
  4.     pinctrl@56000000 {   
  5.             定义S3C2416 pin controller自己的属性  
  6.   
  7.     ……  
  8.   
  9.             gpf {  
  10.                 gpio-controller;  
  11.                 #gpio-cells = <0x2>;  
  12.                 interrupt-controller;  
  13.                 #interrupt-cells = <0x2>;  
  14.                 linux,phandle = <0xc>;  
  15.                 phandle = <0xc>;  
  16.             };  
  17.   
  18.     ……  
  19.   
  20.     }  

每个pin configuration都是pin controller的child node,描述了client device要使用到的一组pin的配置信息。具体如何定义pin configuration是和具体的pin controller相关的。

phandle(linux,phandle这个属性和phandle是一样的,只不过linux,phandle是old-style,多定义一个属性是为了兼容)定义了一个句柄,当其他的device node想要引用这个node的时候就可以使用该句柄。

第二类如下:

uart的pin configuration,代码如下:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. pinctrl@56000000 {   
  2.         定义S3C2416 pin controller自己的属性  
  3.   
  4. ……  
  5.   
  6. uart0-data {  
  7.     samsung,pins = "gph-0""gph-1";  
  8.     samsung,pin-function = <0x2>;  
  9.     linux,phandle = <0x2>;  
  10.     phandle = <0x2>;  
  11. };  
  12.   
  13. uart0-fctl {  
  14.     samsung,pins = "gph-8""gph-9";  
  15.     samsung,pin-function = <0x2>;  
  16.     linux,phandle = <0x3>;  
  17.     phandle = <0x3>;  
  18. };  
  19.   
  20. ……  
  21.   
  22. }  

samsung,pins这个属性定义了一个pin configuration所涉及到的引脚。

对于uart0-data这个node,该配置涉及了gph bank中的第一个和第二个GPIO pin。一旦选择了一个功能,那么samsung,pins定义的所有的引脚都需要做相应的功能设定,那么具体设定什么值呢?这就是samsung,pin-function定义的内容了。而具体设定哪个值则需要去查阅datasheet了。对于uart0-data,向gph bank中的第一个和第二个GPIO pin对应的配置寄存器中写入2就可以把这两个pin定义为uart功能。


3.client device的DTS

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. device-node-name {   
  2.         定义该device自己的属性    
  3.   
  4.         pinctrl-names = "sleep""active";------(1)  
  5.         pinctrl-0 = <pin-config-0-a>;--------------(2)  
  6.         pinctrl-1 = <pin-config-1-a pin-config-1-b>;          
  7.     };  

(1)pinctrl-names定义了一个state列表。那么什么是state呢?对于一个client device,它使用了一组pin,这一组pin应该同时处于某种状态,毕竟这些pin是属于一个具体的设备。state的定义和电源管理关系比较紧密,例如当设备active的时候,我们需要pin controller将相关的一组pin设定为具体的状态,而当设备进入sleep状态的时候,需要pin controller将相关的一组pin设定为普通GPIO。state有两种标识,一种就是pinctrl-names定义的字符串列表,另外一种就是ID。ID从0开始,依次加一。根据例子中的定义,state ID等于0(名字是active)的state对应pinctrl-0属性,state ID等于1(名字是idle)的state对应pinctrl-1属性。具体设备的state的定义请参考在自己的device bind。

(2)pinctrl-x的定义。pinctrl-x是一个句柄(phandle)列表,每个句柄指向一个pin configuration。有时候,一个state对应多个pin configure。例如在active的时候,I2C功能有两种配置,一种是从pin ID{7,8}引出,另外一个是从pin ID{69,103}引出。

我们选取samsung串口的dts定义如下:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. serial@50000000 {   
  2.         ……  
  3.         pinctrl-names = "default";  
  4.         pinctrl-0 = <0x2 0x3>;  
  5.     };   
该serial device只定义了一个state就是default,对应pinctrl-0属性定义。pinctrl-0是一个句柄(phandle)列表,每个句柄指向一个pin configuration。0x2对应上节中的uart0-data节点,0x03对应uart0-fctl 节点,也就是说,这个串口有两种配置,一种是从gph bank中的第一个和第二个GPIO pin引出,另外一个是从gph bank中的第8个和第9个GPIO pin引出。
0 0
原创粉丝点击