Devicetree SpecificationRelease 之(2)THE DEVICETREE

目录

2.1 Overview

2.2 Devicetree Structure and Conventions


2.1 Overview

DTSpec采用了一个称为设备树的数据结构来描述系统的硬件信息。引导程序(BootLoader)将设备树加载到客户端程序的某段内存空间中,并将指向该设备树地址的指针传递给客户端。

本章描述设备树的基本逻辑结构,定义了用于描述设备节点的基本属性集。在第三章中,会定义设备树所需的某些设备节点。第4章描述了dtspec定义的设备绑定——代表某些设备类型或设备类别的要求。第五章描述了如何编写设备树。

设备树是一种树状的数据结构,类似于由设备节点组成的一棵树。用来描述系统中设备的节点。每个节点都有描述所属设备特征的键值对。除了没有父节点的根节点之外,每个节点都只有一个父节点。

设备树描述了系统中不能被客户端驱动程序程序动态检测到的设备信息。例如,PCI的体系结构使客户端能够探测和检测连接的设备信息,因此不需要用设备树节点来面熟PCI设备的信息。但是,如果探测不到系统中的PCI主机桥接设备,则需要一个设备节点来描述该设备。

Example
图2.1是一个简单的设备树示例,但是它足够完整,可以移动一个简单的操作系统。描述了平台类型、CPU、内存和一个UART设备。设备节点在每个节点中显示属性和值。

2.2 Devicetree Structure and Conventions
 

2.2.1 Node Names
 

设备树上各节点的命名规则如下:

node-name@unit-address
node-name描述了节点的名字,长度为1 - 31个字符。仅支持下表的符号构成。

节点名应以小写或大写字符开头,并应描述设备的一般类别

unit-address 描述节点所在的总线类型。unit-address必须与节点的reg属性中指定的第一个地址匹配。如果该节点没有reg属性,则必须省略@unit-address,仅通过节点名将该节点与树中相同级别的其他节点区分开来。对特定总线的绑定可能会对reg格式和unit-address的格式指定额外的、更具体的要求。

根节点没有节点名或单元地址。它由一个正斜杠(/)标识。

· 名称为cpu的节点通过其单位地址值0和1来区分。

· 名称为ethernet的节点通过其单位地址值fe002000和fe003000来区分。

2.2.2 Generic Names Recommendation
 

节点的名称应该是通用的,反映设备的功能。以下是一些恰当的节点名称:

• adc   • accelerometer • atm  • audio-codec  • audio-controller  • backlight  • bluetooth  • bus
• cache-controller  • camera  • can  • charger  • clock • clock-controller  • compact-flash • cpu
• cpus • crypto • disk • display • dma-controller • dsi • dsp • eeprom • efuse • endpoint • ethernet • ethernet-phy • fdc • flash • gnss • gpio • gpu • gyrometer • hdmi • hwlock • i2c • i2c-mux • ide • interrupt-controller • iommu • isa • keyboard • key • keys • lcd-controller • led • leds • led-controller • light-sensor • magnetometer • mailbox • mdio • memory • memory-controller • mmc • mmc-slot • mouse • nand-controller • nvram • oscillator • parallel • pc-card • pci • pcie • phy • pinctrl • pmic • pmu • port • ports • power-monitor • pwm • regulator • reset-controller • rng • rtc • sata • scsi • serial • sound • spi • sram-controller • ssi-controller • syscon • temperature-sensor • timer • touchscreen • tpm • usb • usb-hub • usb-phy • video-codec • vme • watchdog • wifi
 

2.2.3 Path Names
 

通过指定从根节点通过所有子节点到所需节点的完整路径,可以唯一标识设备树中的节点。

指定设备路径的约定是:

/node-name-1/node-name-2/node-name-N
例如,在图2.2中,到cpu #1的设备路径为:

/cpus/cpu@1
根节点的路径为“/”。

如果到节点的完整路径是明确的,则可以省略unit address。

如果客户端程序遇到不明确的节点路径,则它的行为是未定义的。

2.2.4 Properties

设备树中的每个节点都具有描述该节点特征的属性。属性由名称和值的键值对组成。

Property Names
非标准属性名称应该指定唯一的字符串前缀,例如股票行情符号,标识定义该属性的公司或组织的名称。例如:

fsl,channel-fifo-len
ibm,ppc-interrupt-server#s
linux,network-index


Property Values
属性值是一个包含0个或多个字节的数组,这些字节包含与属性相关的信息。

如果传递true/false信息,属性可能是一个空值。因为该属性的存在或不存在通过属性名字就足够描述了。

表2.3描述了DTSpec定义的一组基本值类型。

2.3 Standard Properties
 

DTSpec为设备节点指定了一组标准属性。本节将详细描述这些属性。由DTSpec(见第3章)定义的设备节点可以指定关于标准属性使用的附加要求或约束。第4章描述了特定设备的表示,也可能指定其他要求。

2.3.1 compatible
属性名称: compatible
值类型: <stringlist>

compatible属性值由一个或多个字符串组成,这些字符串定义了设备的特定编程模型,也就是设备匹配的驱动程序名称。这个字符串列表应该被客户端程序用来选择设备驱动程序。如果包含多个字符串,则第一个是优先级最高的匹配驱动名称。它们允许一个设备表达其与一系列类似设备的兼容性,可能允许一个设备驱动程序与多个设备进行匹配。推荐的格式为“manufacturer,model”,其中manufacturer是一个描述制造商名称的字符串(例如股票行情符号),model是指产品型号。

compatible = "fsl,mpc8641", "ns16550";

在这个例子中,操作系统将首先尝试找到支持fsl的设备驱动程序mpc8641。如果没有找到驱动程序,它将尝试找到支持更通用的ns16550设备类型的驱动程序。

2.3.2 model

属性名: model
属性类型: <string>

model属性值是一个<string>,它指定了制造商的设备型号。

推荐格式为:“manufacturer,model”,其中manufacturer是一个描述制造商名称的字符串(如股票行情符号),model是指产品型号。

model = "fsl,MPC8349EMITX";
 

2.3.3 phandle

属性名字: phandle
属性类型: <u32>

phandle属性为设备树中唯一的节点指定一个数字标识符。phandle属性值由需要引用与该属性关联的节点的其他节点使用。phandle为节点定义一个唯一的标识数字,其他节点可以直接引用这个数字

note:DTS中的大多数设备树(见附录A)不会包含显式的phandle属性。当DTS被编译成二进制DTB格式时,DTC工具会自动插入phandle属性。

2.3.4 status

节点名字: status
节点类型: <string>

status属性表示设备的运行状态。表中列出并定义了有效值

2.3.5 #address-cells and #size-cells

节点名字: #address-cells, #size-cells
节点类型: <u32>

#address-cells和#size-cells属性可以用于设备树层次结构中具有子节点的任何设备节点,并描述了如何处理子设备节点。

#address-cells属性定义了用于编码子节点的reg属性中的地址字段的<u32>单元格的数量。

#size-cells属性定义了用于编码子节点的reg属性中的size字段的<u32>单元格的数量。

#address-cells和#size-cells属性不会从设备树中的祖先继承。它们应明确界定。

具有子节点的节点必须明确指明#address-cells和#size-cells属性,否则客户端程序假定#address-cells的默认值为2,而#address-cells的默认值为1。

例如:在这个例子中,soc节点的#address-cells和#size-cells属性都被设置为1。此设置指定需要一个单元格来表示一个地址,需要一个单元格来表示该节点的子节点的大小。serial设备reg属性必须遵循父节点(soc)中设置的这个规范—地址由单个单元(0x4600)表示,大小由单个单元(0x100)表示。

soc {
    #address-cells = <1>;
    #size-cells = <1>;
    serial@4600 {
        compatible = "ns16550";
        reg = <0x4600 0x100>;
        clock-frequency = <0>;
        interrupts = <0xA 0x8>;
        interrupt-parent = <&ipic>;
    };
};

2.3.6 reg
节点名字: reg
节点类型: <prop-encoded-array> encoded as an arbitrary number of (address, length) pairs.

reg属性描述了该设备在其父总线定义的地址空间内的资源地址。最常见的是,这意味着内存映射的IO寄存器块的偏移量和长度,但在某些总线类型上可能有不同的含义。根节点定义的地址空间中的地址为CPU实地址。

该值是一个<prop-encoded-array>,由任意数量的地址和长度对组成,<地址>长度。指定地址和长度所需的<u32>单元的数量是特定于总线的,由设备节点的父节点的#address-cells和#size-cells属性指定。如果父节点为#size-cells指定值为0,则reg值中的长度字段将被省略。

假设片上系统中的一个设备有两个寄存器块,一个32字节的块在SOC中的偏移量为0x3000,一个256字节的块在偏移量为0xFE00。reg属性将按如下方式编码(假设
#address-cells and #size-cells values = 1)

reg = <0x3000 0x20 0xFE00 0x100>;

2.3.7 virtual-reg

节点名字: virtual-reg
节点类型: <u32>

virtual-reg属性指定一个有效地址,该地址映射到设备节点的reg属性中指定的第一个物理地址。此属性使引导程序能够提供已设置的虚拟到物理映射的客户机程序。

2.3.8 ranges
节点名字: ranges
节点类型: <empty> or <prop-encoded-array> encoded as an arbitrary number of (child-bus-address, parentbus-address, length) triplets.

ranges属性提供了一种定义总线地址空间(子地址空间)和总线节点的父节点地址空间(父地址空间)之间映射或转换的方法。

子总线地址是子总线地址空间中的一个物理地址。表示地址的单元数依赖于总线,可以从此节点(range属性出现的节点)的#address-cells确定。

父总线地址是父总线地址空间中的一个物理地址。表示父地址的单元数依赖于总线,可以从定义父地址空间的节点的#address-cells属性确定。

长度指定子地址空间中范围的大小。表示大小的单元数可以从该节点(range属性出现的节点)的#size-cells中确定。

如果属性定义了一个<空>值,它指定父和子地址空间是相同的,不需要地址转换。

如果总线节点中不存在该属性,则假定该节点的子节点和父地址空间之间不存在映射。

例子:

soc {
    compatible = "simple-bus";
    #address-cells = <1>;
    #size-cells = <1>;
    ranges = <0x0 0xe0000000 0x00100000>;
    serial@4600 {
        device_type = "serial";
        compatible = "ns16550";
        reg = <0x4600 0x100>;
        clock-frequency = <0>;
        interrupts = <0xA 0x8>;
        interrupt-parent = <&ipic>;
    };
};

2.3.9 dma-ranges

属性名字: dma-ranges
属性类型: <empty> or <prop-encoded-array> encoded as an arbitrary number of (child-bus-address, parentbus-address, length) triplets.

DMA -ranges属性用于描述内存映射总线的直接内存访问(DMA)结构,该总线的设备树父节点可以通过源自该总线的DMA操作访问。它提供了一种方法来定义总线的物理地址空间和总线父节点的物理地址空间之间的映射或转换。

dma-ranges属性值的格式是任意数量的三元组(child-bus-address, parent-bus-address, length)。每个指定的三元组描述了一个连续的DMA地址范围。

子总线地址是子总线地址空间中的一个物理地址。表示地址的单元数取决于总线,可以从该节点的#address-cells确定(dma-ranges属性出现的节点)。

父总线地址是父总线地址空间中的一个物理地址。表示父地址的单元数依赖于总线,可以从定义父地址空间的节点的#address-cells属性确定。

长度指定子地址空间中范围的大小。表示大小的单元数可以从该节点(dma-ranges属性出现的节点)的#size-cells中确定。

2.3.10 name (废弃)

节点名字: name
节点属性: <string>

2.3.11 device_type (废弃)
节点名字: device_type
节点类型: <string>

2.4 Interrupts and Interrupt Mapping


DTSpec采用中断树模型来表示Open Firmware Recommended Practice中指定的中断:中断映射,版本0.9 [b7]。在设备树中存在一个逻辑中断树,它表示平台硬件中中断的层次结构和路径。虽然通常被称为中断树,但它在技术上更像是一个有向无环图。

在带有interrupt-parent属性的设备树中表示中断源到中断控制器的物理连接。

代表中断产生设备的节点通常包含一个interrupt-parent属性,该属性的值类型是phandle,该值指向设备的中断被连接到的设备,通常是一个中断控制器。如果一个产生中断的设备没有interrupt-parent属性,那么它的中断父设备被假定为它的设备树父设备。

每个产生中断的设备都包含一个interrupt属性,该属性的值描述了该设备的一个或多个中断源。

每个源都用称为Interrupt specifier的信息表示。Interrupt specifier的格式和含义是中断域特定的,也就是说,它依赖于其中断域根节点上的属性。中断域的根节点使用#interrupt-cells属性来定义编码Interrupt specifier所需的<u32>值的数量。对于Open PIC中断控制器,一个中断指示器取两个
32位值,由中断号和中断的level/sense信息组成。

An interrupt domain is the context in which an interrupt specifier is interpreted. The root of the domain is either

(1) an interrupt controller or (2) an interrupt nexus.

1. 中断控制器是一个物理设备,需要一个驱动程序来处理通过它路由的中断。它也可以级联到另一个中断域。中断控制器由设备树中该节点上的中断控制器属性指定。

2. 中断关系定义了一个中断域和另一个中断域之间的转换。转换基于特定于领域和特定于总线的信息。域之间的转换是通过interruptmap属性执行的。例如,一个PCI控制器设备节点可以是一个中断连接,它定义了从PCI中断名称空间(INTA、INTB等)到带有中断请求(IRQ)号的中断控制器的转换。

如图2.3 中的例子:

open-pic中断控制器是中断树的根节点。

中断树的根节点有三个子设备,它们将中断直接路由到open-pic

– device1
– PCI host controller
– GPIO Controller

存在三个中断域;一个根在open-pic节点,一个根在PCI主机桥节点,一个根在GPIO Controller节点。

有两个nexus节点;一个在PCI主机桥上,一个在GPIO控制器上。

2.4.1 Properties for Interrupt Generating Devices
 

interrupts
 

属性名字: interrupts
值类型: <prop-encoded-array> encoded as arbitrary number of interrupt specifiers

设备节点的interrupts属性定义了一个或多个由设备产生的中断。

interrupts属性的值由任意数量的interrupt specifiers组成。

中断指示符的格式由中断域根的绑定定义。

interrupts被Interrupts -extended属性覆盖,通常只应该使用其中一个。

例子:

在开放的pic兼容中断域中,中断指示符的公共定义包括两个单元;中断号和电平/检测信息。请看下面的例子,它定义了一个中断指示符,其中断数为0xA,level/sense编码为8

interrupts = <0xA 8>;

interrupt-parent
 

属性名字: interrupt-parent
值类型: <phandle>

因为中断树中节点的层次结构可能与设备树不匹配,所以interrupt-parent属性可用来显式定义中断父节点。该值是中断父类的句柄。如果设备中缺少此属性,则假定其中断父节点为其设备树父节点。

interrupts-extended
 

属性名字: interrupts-extended
值类型: <phandle> <prop-encoded-array>


中断扩展属性列出了由一个设备产生的中断。当一个设备连接到多个中断控制器时,应该使用interrupts-extended代替interrupts,因为它用每个中断指示符来编码一个父phandle。

例子:

这个例子展示了一个设备如何使用中断扩展属性来描述连接到两个单独的中断控制器的两个中断输出。PIC是一个中断控制器#interrupt-cells指示符为2,而gic是一个中断控制器,其# interrup- cells指示符为1。

interrupts-extended = <&pic 0xA 8>, <&gic 0xda>;

interrupts和interrupts-extended属性是互斥的。设备节点应该使用其中之一,但不能同时使用两者。只有当需要与不理解中断扩展的软件兼容时,才允许使用两者。如果同时存在中断扩展和中断,则中断扩展优先。

2.4.2 Properties for Interrupt Controllers
 

#interrupt-cells
 

属性名称: #interrupt-cells
值类型: <u32>

#interrupt-cells属性定义了为中断域编码中断指示符所需的单元数。

interrupt-controller
 

属性名称: interrupt-controller
值类型: <empty>

中断控制器属性的存在将节点定义为中断控制器节点。

2.4.3 Interrupt Nexus Properties


一个中断连接节点应该有一个#interrupt-cells属性。

interrupt-map
 

属性名称: interrupt-map
值类型: <prop-encoded-array> encoded as an arbitrary number of interrupt mapping entries.
 

中断映射是一个nexus节点上的一个属性,它将一个中断域与一组父中断域连接起来,并指定了子域中的中断指示符如何映射到它们各自的父域。

中断映射是一个表,其中的每一行都是一个由五个组件组成的映射项:子单元地址、子中断指示符、中断-父、父单元地址、父中断指示符。

interrupt-map-mask

属性名称: interrupt-map-mask
值类型: <prop-encoded-array> encoded as a bit mask

为中断树中的一个nexus节点指定了一个中断-映射-掩码属性。此属性指定一个掩码,该掩码应用于在interrupt-map属性中指定的表中查找的传入单元中断指示符。

#interrupt-cells
 

属性名称: #interrupt-cells
值类型: <u32>

#interrupt-cells属性定义了为中断域编码中断指示符所需的单元数。

2.4.4 Interrupt Mapping Example

下面显示了一个带有PCI总线控制器的设备树片段的表示,以及一个描述两个PCI插槽(IDSEL 0x11,0x12)的中断路由的示例中断映射。插槽1和插槽2的INTA, INTB, INTC和INTD引脚连接到Open PIC中断控制器。

soc {
    compatible = "simple-bus";
    #address-cells = <1>;
    #size-cells = <1>;
    open-pic {
        clock-frequency = <0>;
        interrupt-controller;
        #address-cells = <0>;
        #interrupt-cells = <2>;
    };
    pci {
        #interrupt-cells = <1>;
        #size-cells = <2>;
        #address-cells = <3>;
        interrupt-map-mask = <0xf800 0 0 7>;
        interrupt-map = <
            /* IDSEL 0x11 - PCI slot 1 */
            0x8800 0 0 1 &open-pic 2 1 /* INTA */
            0x8800 0 0 2 &open-pic 3 1 /* INTB */
            0x8800 0 0 3 &open-pic 4 1 /* INTC */
            0x8800 0 0 4 &open-pic 1 1 /* INTD */
            /* IDSEL 0x12 - PCI slot 2 */
            0x9000 0 0 1 &open-pic 3 1 /* INTA */
            0x9000 0 0 2 &open-pic 4 1 /* INTB */
            0x9000 0 0 3 &open-pic 1 1 /* INTC */
            0x9000 0 0 4 &open-pic 2 1 /* INTD */
        >;
    };
};

2.5 Nexus Nodes and Specifier Mapping
 

2.5.1 Nexus Node Properties

<specifier>-map
属性名称: <specifier>-map
值类型: <prop-encoded-array> encoded as an arbitrary number of specifier mapping entries.

<specifier>-map-mask
Property: <specifier>-map-mask
Value type: <prop-encoded-array> encoded as a bit mask
 

<specifier>-map-pass-thru
Property: <specifier>-map-pass-thru
Value type: <prop-encoded-array> encoded as a bit mask
 

#<specifier>-cells
Property: #<specifier>-cells
Value type: <u32>
 

2.5.2 Specifier Mapping Example
 

soc {
    soc_gpio1: gpio-controller1 {
    #gpio-cells = <2>;
};

soc_gpio2: gpio-controller2 {
    #gpio-cells = <2>;
    };
};
connector: connector {
    #gpio-cells = <2>;
    gpio-map = <0 0 &soc_gpio1 1 0>,
    <1 0 &soc_gpio2 4 0>,
    <2 0 &soc_gpio1 3 0>,
    <3 0 &soc_gpio2 2 0>;
    gpio-map-mask = <0xf 0x0>;
    gpio-map-pass-thru = <0x0 0x1>;
};

expansion_device {
    reset-gpios = <&connector 2 GPIO_ACTIVE_LOW>;
};

未完待续

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值