设备树的一些知识点

参考网址: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区域。

    ranges = <0 0  0x10100000   0x10000     // Chipselect 1, Ethernet  
              1 0  0x10160000   0x10000     // Chipselect 2, i2c controller  
              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就有如下文字说明:

    01   The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI  
    02   interrupts.  
    03  
    04   The 2nd cell contains the interrupt number for the interrupt type.  
    05   SPI interrupts are in the range [0-987].  PPI interrupts are in the  
    06   range [0-15].  
    07  
    08   The 3rd cell is the flags, encoded as follows:  
    09         bits[3:0] trigger type and level flags.  
    10                 1 = low-to-high edge triggered  
    11                 2 = high-to-low edge triggered  
    12                 4 = active high level-sensitive  
    13                 8 = active low level-sensitive  
    14         bits[15:8] PPI interrupt cpu mask.  Each bit corresponds to each of  
    15         the 8 possible cpus attached to the GIC.  A bit set to '1' indicated  
    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结构:


    pinctrl@56000000 { 
            定义S3C2416 pin controller自己的属性

            定义属于S3C2416 pin controller的pin configurations

    }

samsung 24xx系列SOC的pin controller的pin configurations包括两类,一类是定义pin bank,另外一类是定义功能复用配置。
第一类如下:

    pinctrl@56000000 { 
            定义S3C2416 pin controller自己的属性

    ……

            gpf {
                gpio-controller;
                #gpio-cells = <0x2>;
                interrupt-controller;
                #interrupt-cells = <0x2>;
                linux,phandle = <0xc>;
                phandle = <0xc>;
            };

    ……

    }

每个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,代码如下:


    pinctrl@56000000 { 
            定义S3C2416 pin controller自己的属性

    ……

    uart0-data {
        samsung,pins = "gph-0", "gph-1";
        samsung,pin-function = <0x2>;
        linux,phandle = <0x2>;
        phandle = <0x2>;
    };

    uart0-fctl {
        samsung,pins = "gph-8", "gph-9";
        samsung,pin-function = <0x2>;
        linux,phandle = <0x3>;
        phandle = <0x3>;
    };

    ……

    }

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


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

            pinctrl-names = "sleep", "active";------(1)
            pinctrl-0 = <pin-config-0-a>;--------------(2)
            pinctrl-1 = <pin-config-1-a pin-config-1-b>;        
        };

(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定义如下:

serial@50000000 { 
        ……
        pinctrl-names = "default";
        pinctrl-0 = <0x2 0x3>;
    }; 
该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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值