【问题标题】:Understanding the Device Tree mechanism了解设备树机制
【发布时间】:2013-12-29 04:53:35
【问题描述】:

正在阅读 Device Tree Usage 并到达描述节点的 ranges 键属性的部分。

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>;
            interrupts = < 5 2 >;
        };

        i2c@1,0 {
            compatible = "acme,a1234-i2c-bus";
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <1 0 0x1000>;
            interrupts = < 6 2 >;
            rtc@58 {
                compatible = "maxim,ds1338";
                reg = <58>;
                interrupts = < 7 3 >;
            };
        };

        flash@2,0 {
            compatible = "samsung,k8f1315ebm", "cfi-flash";
            reg = <2 0 0x4000000>;
        };
    };
  1. rangesreg 有什么区别?
  2. 范围的维度是多少,解析器如何确定其中写入的内容?
  3. 缺少一个我还不明白的部分?不能在 .dts 文件中包含 .h 文件而不是硬编码值?

【问题讨论】:

标签: linux kernel device device-tree


【解决方案1】:

“范围”属性将当前节点(“外部总线”节点)中的一个或多个地址(范围左侧的第二个数字)映射到父节点(可能是 CPU)地址空间中的地址(范围内的第三个数字)。第四个数字是范围的长度。总线可以对连接外围设备的外部地址有自己的想法,因此管理总线上外围设备的驱动程序需要知道这些范围才能读取或写入设备。

“reg”属性表示设备在定义设备的节点(在本例中为“外部总线”)的地址范围内的地址。所以在这种情况下,flash@2,0 位于外部总线范围内的地址 0,并扩展到地址 0x04000000。这对应于父 (CPU) 地址空间中的地址范围 0x30000000 到 0x34000000。

我假设第三个范围的长度说明符 2 0 0x30000000 0x1000000&gt;; // Chipselect 3, NOR Flash 实际上应该是 0x04000000 而不是 0x1000000

【讨论】:

  • 为什么您认为 Nor Flash 的长度说明符不正确?如果它是 0x1000000,那么它的范围从 0x30000000 到 0x30ffffff (16MB),如果它的 0x04000000,那么它的范围从 0x30000000 到 0x03ffffff (64MB) 内存用于闪存。
【解决方案2】:

对于这个特殊的例子,Jonathan Ben-Avraham 的解释是正确的。但是最好了解设备树中ranges属性的详细结构。

  • ranges 是地址转换列表。
  • 范围表中的每个条目都是一个包含 child 的元组 地址父地址和子区域的大小 地址空间。

喜欢

ranges = < Child1Address ParentAddressForChild1 sizeofchild1 
           Child2Address ParentAddressForChild2 sizeofchild2
           Child3Address ParentAddressForChild3 sizeofchild3
>;
  • 每个字段的大小如下确定

为了取子地址大小检查#address-cells子节点的值。

用于计算其父节点的父地址大小检查#address-cells值,

用于取子节点大小检查#size-cells值的长度。


示例 1:作为问题提及

    #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

让我们解码第一个条目。

  1. 子地址单元格大小为 2,因此前两个条目提及子地址。 (此地址仅特定于本地子地址) 进一步如何解码这两个条目是设备特定的。设备驱动程序应该有这些文件)
  2. 父地址单元格大小为 1,因此下一个条目是该子节点的父地址。
  3. child size-cells 为 1,因此下一个条目是 child 的范围(写入到父地址。)

示例 2:PCI 设备条目

#address-cells = <1>;
#size-cells = <1>;
pci@0x10180000 {
    compatible = "arm,versatile-pci-hostbridge", "pci";
    reg = <0x10180000 0x1000>;
    interrupts = <8 0>;
    bus-range = <0 0>;

    #address-cells = <3>
    #size-cells = <2>;
    ranges = <0x42000000 0 0x80000000 0x80000000 0 0x20000000
              0x02000000 0 0xa0000000 0xa0000000 0 0x10000000
              0x01000000 0 0x00000000 0xb0000000 0 0x01000000>;

这里

0x42000000 0 0x80000000是child1的地址。 PCI驱动文档中提到了如何解码这3个条目。

0x80000000 是父地址。父节点是cpu,所以从cpu这个地址是用来和这个设备通信的。

0 0x20000000 是该设备在父地址空间中的大小。 (0 到 512MB 地址)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    相关资源
    最近更新 更多