根节点始终描述的是 CPU 视角的地址空间。根节点的子节点已经使用的是 CPU 的地址域,所以它们不需要任何直接映射。例如,serial@101f0000 设备就是直接分配的 0x101f0000 地址
非根节点直接子节点的节点就没有使用 CPU 地址域。为了得到一个内存映射地址,设备树必须指定从一个域到另一个域地址转换地方法,而 ranges 属性就为此而生。
/ { 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 表中的每一项都是一个包含子地址、父地址和在子地址空间中区域大小的元组
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 、父节点的 #address-cells 和子节点的 #size-cells。以本例中的外部总线来说,子地址是 2 cell、父地址是 1 cell、区域大小也是 1 cell
i2c@1,0 节点中并没有 range 属性,这里的原因是 i2c 总线上的设备并没有被内存映射到 CPU 的地址域。CPU 将通过 i2c@1,0 设备间接访问 rtc@58 设备
缺少 ranges 属性意味着这个设备将不能被出他的父设备之外的任何设备直接访问。