通过在父节点设置合适的#address-cells和#size-cells,地址映射机制可以准确的描述内存映射关系。下面的代码中展示了一个不同片选信息在是如何使用的。
external-bus { #address-cells = <2> #size-cells = <1>; ethernet@0,0 { compatible = "smc,smc91c111"; reg = <0 0 0x1000>; }; i2c@1,0 { compatible = "acme,a1234-i2c-bus"; reg = <1 0 0x1000>; rtc@58 { compatible = "maxim,ds1338"; }; }; flash@2,0 { compatible = "samsung,k8f1315ebm", "cfi-flash"; reg = <2 0 0x4000000>; }; };
上面的例子中,external-bus使用了两个cell来描述address;一个表示片选号,另一个表示与片选基地址间的偏移量。length区域则用了一个cell来描述。在这个例子中,每个reg节点包含3个cell,分别是:片选号,偏移量,长度
非内存映射设备
还有一些设备在总线上并不是不是内存映射型的。他们可以有地址空间,但他们没有通过CPU直接访问地址空间的能力。取而代之的是他们的父设备驱动拥有间接访问内存空间的能力。
以I2C设备(不是I2C总线哦)为例子,每个设备被分配了一个地址,没有length这个字段。看起来实际上与cpu的地址分配很相似。
i2c@1,0 { compatible = "acme,a1234-i2c-bus"; #address-cells = <1>; #size-cells = <0>; reg = <1 0 0x1000>; rtc@58 { compatible = "maxim,ds1338"; reg = <58>; }; };
Ranges(地址变换)
上文已经讨论过了我们如何分配地址给设备,但是这个所谓的地址仅仅是在设备节点中的本地地址。它无法描述该如何将这些本地的地址映射到CPU能访问的地址空间中。
根节点中一定有描述CPU的地址空间。子节点所用的地址空间就来自与CPU的地址空间,所以不需要进行额外的地址映射。
如:serial@101f0000 就是直接分配的地址0x101f0000。
如果一个节点它不是跟节点下的子节点,那么它就不能用CPU的地址空间。为了能将一个地址空间的地址映射到另一个地址空间,range属性被创造出来了。
下面是在一个简单的设备树中增加range属性。
/ { compatible = "acme,coyotes-revenge"; #address-cells = <1>; #size-cells = <1>; ... external-bus { #address-cells = <2> #size-cells = <1>; ranges = <0 0 0x10100000 0x10000 // Chipselect 1, Ethernet 1 0 0x10160000 0x10000 // Chipselect 2, i2c controller 2 0 0x30000000 0x1000000>; // Chipselect 3, NOR Flash ethernet@0,0 { compatible = "smc,smc91c111"; reg = <0 0 0x1000>; }; i2c@1,0 { compatible = "acme,a1234-i2c-bus"; #address-cells = <1>; #size-cells = <0>; reg = <1 0 0x1000>; rtc@58 { compatible = "maxim,ds1338"; reg = <58>; }; }; flash@2,0 { compatible = "samsung,k8f1315ebm", "cfi-flash"; reg = <2 0 0x4000000>; }; }; };
上面的例子中,ranges属性就定义了一个地址转换规格。在这个表中的每个节点表示一个地址转换关系。
ranges属性中每个字段的大小取决于当前节点的#address-cells,父节点的#address-cells以及当前节点的#size-cells。
比如上面的例子中,external-bus节点的地址长度是2,它的父节点的地址长度是1,size长度是1。所以ranges中的三个地址规则可以这样解读:
CS0,偏移量为0的本地地址被映射到父节点地址空间的 0x10100000~0x1010ffff
CS1,偏移量为1的本地地址被映射到父节点地址空间的 0x10160000~0x1016ffff
CS2,偏移量为0的本地地址被映射到父节点地址空间的 0x30000000~0x31000000
更方便的是,如果父节点与子节点的地址空间完全匹配,则子节点可以只定义一个空的ranges属性。
空ranges属性所表示的意思就是子节点的地址空间与父节点地址空间是1:1的映射关系。