設備樹中ranges屬性分析(1)


作者

彭東林
pengdonglin137@163.com
 

軟件環境

Linux-4.10.17
Qemu+vexpress
 

概述

在設備樹中有時會看到ranges屬性,這個ranges屬性可以達到什么效果呢? 今天看到宋寶華老師的設備樹講座,才知道。為了有一個直觀的印象,下面我們結合一個實際的例子來看看
 

正文

一、設備樹

下面是我們將要實驗的設備樹的例子:
  1 / {
  2     #address-cells = <1>;
  3     #size-cells = <1>;
  4 
  5     demo_level0 {
  6         compatible = "simple-bus";
  7         ranges = <0x0 0x3000000 0x3000>;
  8         #address-cells = <1>;
  9         #size-cells = <1>;
 10 
 11         range@0 {
 12             compatible = "range";
 13             reg = <0x100 0x200>;
 14             reg-names = "range0";
 15         };
 16 
 17         range@1 {
 18             compatible = "range";
 19             reg = <0x300 0x200>;
 20             reg-names = "range1";
 21         };
 22 
 23         range@2 {
 24             compatible = "range";
 25             reg = <0x600 0x200>;
 26             reg-names = "range2";
 27         };
 28 
 29         demo_level1 {
 30             compatible = "simple-bus";
 31             ranges = <0x0 0x1000 0x1000>;
 32             #address-cells = <1>;
 33             #size-cells = <1>;
 34 
 35             range@3 {
 36                 compatible = "range";
 37                 reg = <0x100 0x200>;
 38                 reg-names = "range3";
 39             };
 40 
 41             demo_level1-1 {
 42                 compatible = "simple-bus";
 43                 ranges = <0x0 0x300 0x500>;
 44                 #address-cells = <1>;
 45                 #size-cells = <1>;
 46 
 47                 range@4 {
 48                     compatible = "range";
 49                     reg = <0x100 0x200>;
 50                     reg-names = "range4";
 51                 };
 52 
 53                 range@5 {
 54                     compatible = "range";
 55                     reg = <0x300 0x100>;
 56                     reg-names = "range5";
 57                 };
 58 
 59                 demo_level1-1-1 {
 60                     compatible = "simple-bus";
 61                     ranges = <0x0 0x400 0x100>;
 62                     #address-cells = <1>;
 63                     #size-cells = <1>;
 64 
 65                     range@6 {
 66                         compatible = "range";
 67                         reg = <0x50 0x30>;
 68                         reg-names = "range6";
 69                     };
 70 
 71                     demo_level1-1-1-1 {
 72                         compatible = "simple-bus";
 73                         ranges = <0x0 0x20 0x20>;
 74                         #address-cells = <1>;
 75                         #size-cells = <1>;
 76 
 77                         range@7 {
 78                             compatible = "range";
 79                             reg = <0x10 0x10>;
 80                             reg-names = "range7";
 81                         };
 82 
 83                         range@8 {
 84                             compatible = "range";
 85                             reg = <0x0 0x10>;
 86                             reg-names = "range8";
 87                         };
 88                     };
 89                 };
 90             };
 91 
 92             range@9 {
 93                 compatible = "range";
 94                 reg = <0x800 0x50>;
 95                 reg-names = "range9";
 96             };
 97 
 98             demo_level1-2 {
 99                 compatible = "simple-bus";
100                 ranges = <0x0 0x900 0x100>;
101                 #address-cells = <1>;
102                 #size-cells = <1>;
103 
104                 range@10 {
105                     compatible = "range";
106                     reg = <0x0 0x50>;
107                     reg-names = "range10";
108                 };
109 
110                 demo_level1-2-1 {
111                     compatible = "simple-bus";
112                     ranges;
113                     #address-cells = <1>;
114                     #size-cells = <1>;
115 
116                     range@11 {
117                         compatible = "range";
118                         reg = <0x50 0x30>;
119                         reg-names = "range11";
120                     };
121                 };
122             };
123         };
124 
125         demo_level2 {
126             compatible = "simple-bus";
127             ranges;
128             #address-cells = <1>;
129             #size-cells = <1>;
130 
131             range@12 {
132                 compatible = "range";
133                 reg = <0x2000 0x1000>;
134                 reg-names = "range12";
135             };
136         };
137     }
138 };
 

二、驅動

下面是一個簡單的驅動,功能很簡單,只是在probe函數中將memory資源的start和(end+1)打印出來.
demo_range.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>

static int demo_range_probe(struct platform_device *pdev)
{
    struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

    printk(KERN_INFO "%s start: 0x%x, end: 0x%x\n",
        res->name, res->start, res->end + 1);

    return 0;
}

static int demo_range_remove(struct platform_device *pdev)
{
    return 0;
}

static const struct of_device_id demo_range_of_match[]  = {
    { .compatible = "range"},
    {},
};

static struct platform_driver demo_range_driver = {
    .driver = {
        .name = "demo_range",
        .owner = THIS_MODULE,
        .of_match_table = demo_range_of_match,
    },
    .probe = demo_range_probe,
    .remove = demo_range_remove,
};
module_platform_driver(demo_range_driver);

MODULE_LICENSE("GPL v2");
在驅動中會獲得memory資源,然后將start和(end+1)打印出來,之所以這里用(end+1),僅僅是為了便於理解下面的kernel log。

三、驗證

編譯驅動,然后加載,可以看到下面的打印信息:
[root@vexpress mnt]# insmod demo_range.ko 
[  382.940402] range0 start: 0x3000100, end: 0x3000300
[  382.940697] range1 start: 0x3000300, end: 0x3000500
[  382.941448] range2 start: 0x3000600, end: 0x3000800
[  382.941657] range3 start: 0x3001100, end: 0x3001300
[  382.941855] range4 start: 0x3001400, end: 0x3001600
[  382.942057] range5 start: 0x3001600, end: 0x3001700
[  382.942262] range6 start: 0x3001750, end: 0x3001780
[  382.942470] range7 start: 0x3001730, end: 0x3001740
[  382.942684] range8 start: 0x3001720, end: 0x3001730
[  382.949796] range9 start: 0x3001800, end: 0x3001850
[  382.950023] range10 start: 0x3001900, end: 0x3001950
[  382.950603] range11 start: 0x3001950, end: 0x3001980
[  382.950805] range12 start: 0x3002000, end: 0x3003000
 
總結:
1、ranges屬性值的格式 <local地址parent地址size>, 表示將local地址向parent地址的轉換。
比如對於#address-cells和#size-cells都為1的話,以<0x0  0x10 0x20>為例,表示將local的從0x0~(0x0 + 0x20)的地址空間映射到parent的0x10~(0x10 + 0x20)
 
其中,local地址的個數取決於當前含有ranges屬性的節點的#address-cells屬性的值,size取決於當前含有ranges屬性的節點的#size-cells屬性的值。
parent地址的個數取決於當前含有ranges屬性的節點的parent節點的#address-cells的值。
 
2、對於含有ranges屬性的節點的子節點來說,其reg都是基於local地址
 
3、ranges屬性值為空的話,表示1:1映射
 
4、對於沒有ranges屬性的節點,代表不是memory map區域
 

四、示意圖

對照上面的log理解下面的框圖
 
 
 
 
完。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM