让你完全理解linux内核设备树ranges属性地址转换


linux下设备树ranges属性详细介绍:
我们在设备树中ranges属性和#address-cells = <1>;#size-cells = <1>;相关联的
#address-cells属性:
#address-cells告诉你我们的地址是32为还是64位 #address-cells = <1>;就是说你的地址是32位,#address-cells = <2>;就是说你的地址是64位,现在的设备树中表示地址范围的#address-cells还没有超过2的 #address-cells只能是1和2
例如:
对于32位的地址#address-cells = <1>:
reg =  <0x02000000 0x10000>这种情况我们很常见了就是 0x02000000~0x02000000+0x10000地址空间
对于64位的地址#address-cells = <2>:
reg =  <0x10000000 0x02000000 0x10000>这种情况我们64位的地址就是高32位是0x10000000,低32位是0x02000000的64位地址所以他代表的地址空间就是:0x1000000002000000 + 0x10000的地址空间

#size-cells属性:表示地址大小范围,这个都能理解

    
理解上边两个属性,ranges的属性就好理解了

举个例子
imx6{
        #address-cells = <1>;
        #size-cells = <1>;
        weim {
            #address-cells = <2>;
            #size-cells = <1>;
            status = "okay";
            /* weim memory map: 32MB on CS0, 32MB on CS1, 32MB on CS2 */
            ranges = <0 0 0x08000000 0x02000000
                      1 0 0x0a000000 0x02000000
                      2 0 0x0c000000 0x02000000>;

            /* TL16C554 on CS0 */
            uarta0@0,0xe000 {
                /* 8250 based simple serial driver */
                compatible = "ti,tl16c554", "ns16550a";
                reg = <0 0xe000 0x8>;
                interrupt-parent = <&gpio4>;
                interrupts = <6 IRQ_TYPE_LEVEL_HIGH>;
                clock-frequency = <3686400>;
            }
            
            uarta1@1,0xe000 {
                /* 8250 based simple serial driver */
                compatible = "ti,tl16c554", "ns16550a";
                reg = <1 0xe000 0x8>;
                interrupt-parent = <&gpio4>;
                interrupts = <6 IRQ_TYPE_LEVEL_HIGH>;
                clock-frequency = <3686400>;
            }
        }
    }

ranges就是地址翻译,他的成员组成如下:
ranges = <local_address parent_address address_size>
local_address:这里local_address就是我们设备树中weim节点的#address-cells = <2>;就是64位地址
parent_address:这里就是我们imx6节点的#address-cells = <1>;就是32位的地址
address_size:就是#size-cells = <1>;

所以上边我们ranges可以映射的地址空间就是:
0地址空间就是:0x08000000~0x08000000+0x02000000
1地址空间就是:0x0a000000~0x0a000000+0x02000000
2地址空间就是:0x0c000000~0x0c000000+0x02000000

所以我们节点uarta0地址空间的计算方法就是 0x08000000 + (0<<32)|(0xe000) - ((0<<32)|(0)) 就是0x0800e0000~0x0800e0008,计算方法和uart1一样


所以我们节点uarta1地址空间的计算方法就是 0x0a000000 + (1<<32)|(0xe000) - ((1<<32)|(0)) 就是0x0a00e0000~0x0a00e0008

下边我们位移是按64位来做的:
off1=这里(1<<32)|(0xe000)就是我们uarta1中reg属性前两个数字组成的64位地址(即0x1代表高32位,0xe000代表低32位)
off2=这里((1<<32)|(0))就是我们ranges=<1 0 0x0a000000 0x02000000>的前两个数字组成的64位地址,(即0x1代表高32位,0x0代表低32位)
所以我们uarta1的地址空间就是0x0a000000 + off1-off2
对于#address-cells = <1>;的情况和上边一样只是地址是32位而已


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM