设备树的一些知识点

来源:互联网 发布:80端口被系统占用 编辑:程序博客网 时间:2024/06/07 06:36

参考网址: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 0
原创粉丝点击