linux设备树的解释 - DT文件数据结构

本文只是DT的入门文章,看明白了本文的介绍,你应该能自己看懂本文没有介绍过的节点/属性所起的作用,比如说dma,power management,soc等等

DT数据结构总括

一个设备树的总体结构如下

  / o device-tree
      |- name = "device-tree"
      |- model = "MyBoardName"
      |- compatible = "MyBoardFamilyName"
      |- #address-cells = <2>
      |- #size-cells = <2>
      |- linux,phandle = <0>
      |
      o cpus
      | | - name = "cpus"
      | | - linux,phandle = <1>
      | | - #address-cells = <1>
      | | - #size-cells = <0>
      | |
      | o PowerPC,970@0
      |   |- name = "PowerPC,970"
      |   |- device_type = "cpu"
      |   |- reg = <0>
      |   |- clock-frequency = <0x5f5e1000>
      |   |- 64-bit
      |   |- linux,phandle = <2>
      |
      o memory@0
      | |- name = "memory"
      | |- device_type = "memory"
      | |- reg = <0x00000000 0x00000000 0x00000000 0x20000000>
      | |- linux,phandle = <3>
      |
      o chosen
        |- name = "chosen"
        |- bootargs = "root=/dev/sda2"
        |- linux,phandle = <4>

下面是个实际的例子:s3c6410-smdk6410板子的设备树

/ {
    model = "SAMSUNG SMDK6410 board based on S3C6410";
    compatible = "samsung,mini6410", "samsung,s3c6410";

    memory {
        reg = <0x50000000 0x8000000>;
    };

    chosen {
        bootargs = "console=ttySAC0,115200n8 earlyprintk rootwait root=/dev/mmcblk0p1";
    };

    clocks {
        compatible = "simple-bus";
        #address-cells = <1>;
        #size-cells = <0>;

        fin_pll: oscillator@0 {
            compatible = "fixed-clock";
            reg = <0>;
            clock-frequency = <12000000>;
            clock-output-names = "fin_pll";
            #clock-cells = <0>;
        };

        xusbxti: oscillator@1 {
            compatible = "fixed-clock";
            reg = <1>;
            clock-output-names = "xusbxti";
            clock-frequency = <48000000>;
            #clock-cells = <0>;
        };
    };

    srom-cs1@18000000 {
        compatible = "simple-bus";
        #address-cells = <1>;
        #size-cells = <1>;
        reg = <0x18000000 0x8000000>;
        ranges;

        ethernet@18000000 {
            compatible = "smsc,lan9115";
            reg = <0x18000000 0x10000>;
            interrupt-parent = <&gpn>;
            interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
            phy-mode = "mii";
            reg-io-width = <4>;
            smsc,force-internal-phy;
        };
    };
};

从上可以得知设备树是由节点组成的,总体上由一个根节点”/”包含,根节点下包含许多子节点,子节点下又包含子节点,节点中又包含许多属性,下面先介绍单元节点,然后介绍每个属性的含义及表达

单个节点组成

单个节点表示

[label:] node-name[@unit-address] { 
   [properties]
   [child nodes]
}

[]表示可选的,一个节点名字组成:

[label:] node-name[@unit-address]

其中node-name是必须有的,@unit-address表示节点所在的地址,label是节点的标签,可以方便其他文件引用此节点,引用的表示为:

&sdhci0 {
    pinctrl-names = "default";
    pinctrl-0 = <&sd0_clk>, <&sd0_cmd>, <&sd0_cd>, <&sd0_bus4>;
    bus-width = <4>;
    status = "okay";
};

sdhci0就是一个label,sdhci0节点在dtsi文件中已经存在了,但是在某一特定板子上要有某些特殊的表示,就可以引用sdhci0节点来定义一些属性
节点下面包含许多属性properties
节点下面包含许多子节点child nodes

属性介绍

cells属性及地址表达

在属性中有一些属性是用来定义子节点的地址规范的,比如属性#address-cells和#size-cells,例如下面的表示:

    #address-cells = <1>;
    #size-cells = <1>;

一个cell可以理解为一小格空间,用<>来表示,里面的数都是32位数据值,和此有关的属性有reg和ranges属性

reg

reg属性的表达为

bus address, size

#address-cells属性定义bus address,#size-cells来定义size,举上面的例子来说:

    srom-cs1@18000000 {
        compatible = "simple-bus";
        #address-cells = <1>;
        #size-cells = <1>;
        reg = <0x18000000 0x8000000>;
        ranges;

        ethernet@18000000 {
            compatible = "smsc,lan9115";
            reg = <0x18000000 0x10000>;
            interrupt-parent = <&gpn>;
            interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
            phy-mode = "mii";
            reg-io-width = <4>;
            smsc,force-internal-phy;
        };
    };

#address-cells = <1>规定了reg = <0x18000000 0x10000>中的0x18000000
#size-cells = <1>规定了reg = <0x18000000 0x10000>中的0x10000
如果#address-cells = <2>,那么reg就应该是像下面这样子的:

reg = < 0x00000000 0x18000000 0x10000>

#address-cells = <2>规定了 0x00000000 0x18000000
还有像这样表达的:

reg = < 0x00000000 0x18000000 0x10000
        0x00000000 0x20000000 0x10000>

这个等同于把两个reg合并到一个reg里面去了,等同于下面的表达

    reg = < 0x00000000 0x18000000 0x10000 >
    reg = < 0x00000000 0x20000000 0x10000 >

用途:reg顾名思义就是代表设备寄存器的地址区间

ranges

ranges的表达为

bus address, parent bus address, size

类似上面reg属性的表达,#address-cells规定了‘bus address, parent bus address‘;#size-cells 规定了‘size‘
用途:ranges属性用于内存的动态映射,在memory节点再详细介绍

“compatible” 属性

compatible属性用于兼容性匹配,在设备驱动中用于和设备驱动来进行匹配,如上面举例:

compatible = "smsc,lan9115";

它会在设备注册中匹配有”smsc,lan9115”标志的驱动,还有一些这样表达:

compatible = "samsung,mini6410", "samsung,s3c6410";

表示会匹配samsung,mini6410和samsung,s3c6410,其实这就是兼容的意思

“name” 属性

name属性现在好多节点都不定义,它类似于device_type属性,在版本16后,如果此属性不存在,那么就会用节点的名字(@前面的名字)来重新定义它

中断属性

interrupts属性和#interrupt-cells属性

#interrupt-cells决定了interrupts有几个值,每个值的定义由中断控制器的具体spec决定
例如:

gic: interrupt-controller@12001000 {
    compatible = "arm,gic-400";
    reg = <0 0x12001000 0 0x1000>,
          <0 0x12002000 0 0x2000>,
          <0 0x12004000 0 0x2000>,
          <0 0x12006000 0 0x2000>;
    #interrupt-cells = <3>;
    interrupt-controller;
    interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8)
                | IRQ_TYPE_LEVEL_HIGH)>;
};

serial0: serial@1c020000 {
    status = "disabled";
    device_type = "serial";
    compatible = "ns16550a";
    reg = <0 0x1c020000 0x0 0x1000>;
    reg-shift = <2>;
    clock-frequency = <10000000>; 
    interrupt-parent = <&gic>;
    interrupts = <0x0 0x4c 0x4>;
};

#interrupt-cells = <3>;决定了interrupts = <0x0 0x4c 0x4>;

OpenPIC的#interrupt-cells = <2>,interrupts的两个值的含义为:中断号和中断触发条件,其中中断触发条件的定义为:

0 = low to high edge sensitive type enabled
1 = active low level sensitive type enabled
2 = active high level sensitive type enabled
3 = high to low edge sensitive type enabled

interrupt-parent属性

此属性决定了节点所依附的中断控制器,如上面的例子中,serial0所依附的中断控制器为gic: interrupt-controller@12001000

属性数据值

某些属性值这么表示:

property = [0x0a 0x0b 0x0c 0x0d 0xde 0xea 0xad 0xbe 0xef];

这是定义属性值为字节数组

property = "a","b","c";

这是定义属性值为字符串数组
还有些属性没值,是空属性

NOTE1:属性就类似于协议的东西,具体驱动中怎么用,可以自己定义
NOTE2:如果你要定义自己的属性,那么最好属性由vendor,string表示

节点介绍

root node

根节点需要有这些属性存在:

- model : this is your board name/model
- #address-cells : address representation for "root" devices
- #size-cells: the size representation for "root" devices
- compatible : the board "family" generally finds its way here,
  for example, if you have 2 board models with a similar layout,
  that typically get driven by the same platform code in the
  kernel, you would specify the exact board model in the
  compatible property followed by an entry that represents the SoC
  model.

/cpus node

节点属性至少有

           #address-cells = <00000001>
           #size-cells    = <00000000>

#address-cells规定了子cpu的地址,见/cpus/* nodes

/cpus/* nodes

节点名字一般这么定义“ < architecture >,< core >”
属性有:

- device_type : has to be "cpu"
- reg : This is the physical CPU number, it's a single 32-bit cell
  and is also used as-is as the unit number for constructing the
  unit name in the full path. For example, with 2 CPUs, you would
  have the full path:
    /cpus/PowerPC,970FX@0
    /cpus/PowerPC,970FX@1
  (unit addresses do not require leading zeroes)
- d-cache-block-size : one cell, L1 data cache block size in bytes (*)
- i-cache-block-size : one cell, L1 instruction cache block size in
  bytes
- d-cache-size : one cell, size of L1 data cache in bytes
- i-cache-size : one cell, size of L1 instruction cache in bytes

其他属性

- timebase-frequency : a cell indicating the frequency of the
  timebase in Hz. This is not directly used by the generic code,
  but you are welcome to copy/paste the pSeries code for setting
  the kernel timebase/decrementer calibration based on this
  value.
- clock-frequency : a cell indicating the CPU core clock frequency
  in Hz. A new property will be defined for 64-bit values, but if
  your frequency is < 4Ghz, one cell is enough. Here as well as
  for the above, the common code doesn't use that property, but
  you are welcome to re-use the pSeries or Maple one. A future
  kernel version might provide a common function for this.
- d-cache-line-size : one cell, L1 data cache line size in bytes
  if different from the block size
- i-cache-line-size : one cell, L1 instruction cache line size in
  bytes if different from the block size

/memory node(s)

定义了板子的物理内存分布
例子:

- device_type : has to be "memory"
- reg : This property contains all the physical memory ranges of
  your board. It's a list of addresses/sizes concatenated
  together, with the number of cells of each defined by the
  #address-cells and #size-cells of the root node. For example,
  with both of these properties being 2 like in the example given
  earlier, a 970 based machine with 6Gb of RAM could typically
  have a "reg" property here that looks like:

  00000000 00000000 00000000 80000000
  00000001 00000000 00000001 00000000

  That is a range starting at 0 of 0x80000000 bytes and a range
  starting at 0x100000000 and of 0x100000000 bytes. You can see
  that there is no memory covering the IO hole between 2Gb and
  4Gb. Some vendors prefer splitting those ranges into smaller
  segments, but the kernel doesn't care.

/chosen node

建议属性

- bootargs : This zero-terminated string is passed as the kernel
  command line
- linux,stdout-path : This is the full path to your standard
  console device if any. Typically, if you have serial devices on
  your board, you may want to put the full path to the one set as
  the default console in the firmware here, for the kernel to pick
  it up as its own default console.

/soc < SOCname> node

此节点适用于SOC(system-on-a-chip),节点名字开始必须是soc(MPC8540->soc8540)
必须的属性

- ranges : Should be defined as specified in 1) to describe the
  translation of SoC addresses for memory mapped SoC registers.
- bus-frequency: Contains the bus frequency for the SoC node.
  Typically, the value of this field is filled in by the boot
  loader.
- compatible : Exact model of the SoC

推荐属性

- reg : This property defines the address and size of the
  memory-mapped registers that are used for the SOC node itself.
  It does not include the child device registers - these will be
  defined inside each child node.  The address specified in the
  "reg" property should match the unit address of the SOC node.
- #address-cells : Address representation for "soc" devices.  The
  format of this field may vary depending on whether or not the
  device registers are memory mapped.  For memory mapped
  registers, this field represents the number of cells needed to
  represent the address of the registers.  For SOCs that do not
  use MMIO, a special address format should be defined that
  contains enough cells to represent the required information.
  See 1) above for more details on defining #address-cells.
- #size-cells : Size representation for "soc" devices
- #interrupt-cells : Defines the width of cells used to represent
   interrupts.  Typically this value is <2>, which includes a
   32-bit number that represents the interrupt number, and a
   32-bit number that represents the interrupt sense and level.
   This field is only needed if the SOC contains an interrupt
   controller.

例子:

soc8540@e0000000 {
    #address-cells = <1>;
    #size-cells = <1>;
    #interrupt-cells = <2>;
    device_type = "soc";
    ranges = <0x00000000 0xe0000000 0x00100000>
    reg = <0xe0000000 0x00003000>;
    bus-frequency = <0>;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值