设备树规格书(Devicetree Specification)
设备树规范阐述了一个用于描述系统硬件被称为设备树的结构。引导程序加载设备树到这client程序的内存中并把指向设备树的指针传给client程序。
本章节主要内容为设备树的逻辑结果和用于描述设备结点的基本属性集。第三章将通过DTSpec-compliant明确设备结点要求。第四章描述了设备树规范中设备bindings--对于清晰表达设备类型和类别的要求。第五章描述了设备树在内存中的编码格式。
设备树是一个树形的数据结构,它的结点描述了系统中对应的设备。每个结点用属性/值(key-value)对来描述设备的特征,并且除了root根结点以外,每个结点都有唯一的父结点。
在系统中,DTSpec-compliant设备树描述的设备信息,client程序不一定能动态的探测到。例如,PCI的架构使能client程序去探测相关/挂载的设备,因此可能不需要描述PCI设备的设备树结点。然而,如果它没能被probing探测到,那描述PCI host bridge设备的设备结点是必要的。
例如
图2.1为一个足够引导一个有平台类型、CPU、内存和串口的简易操作系统的简单设备树表现形式的例子。设备结点是以属性和值表示的。
图2.1 设备树举例
结点命名规则
设备树中的每个结点的命名有如下规则:
node-name@unit-address
其中node-name
描述了结点的名字。它必须由1到31个有效字符(见表2.1)组成。
表2.1 有效字符
字符 | 0 - 9 | a - z | A - Z | , | . | _ | + | - |
---|---|---|---|---|---|---|---|---|
描述 | 数字 | 小写字母 | 大写字母 | 逗号 | 小数点 | 下滑线 | 加号 | 破折号 |
node-name
必须以字母开头且应描述对应设备的类型。
unit-address
明确了结点所在总线的位置。它由一个或多个表2.1中的ASCII
字符组成。unit-address
必须与结点的reg
属性中的首地址匹配。如果结点没有reg
属性,unit-address
必须被省略且node-name
不能与同级其它node-name
相同。特定总线可能会对reg
和unit-address
的格式有其他更多具体的要求。
root根结点没有node-name
和unit-address
,它用/
表示。
图2.2 结点名举例
图2.2:
- 图中名为cpu的结点通过
unit-address
的值0和1来区分 - 图中名为ethernet的结点通过
unit-address
的值fe001000
和fe003000
来区分
结点名应该尽可能的通用且能反映出设备的功能,而不是精确的编程模型。如果合适,应该从下面的名字中选择一个:
- adc
- accelerometer
- atm
- audio-codec
- audio-controller
- backlight
- bluetooth
- bus
- cache-controller
- camera
- can
- charger
- clock
- clock-controller
- compact-flash
- cup
- cups
- 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
设备树中的一个结点能够被从根结点开始的绝对路径所唯一标识,能逐层查找到所描述的结点。
制定一个设备路径的规则是:
/node-name-1/node-name-2/node-name-N
例如,图2.2中cup#1
的路径是:
/cpus/cpu@1
这路径的根结点是/
。
如果对于结点的绝对路径没有争议,那么unit-address
可以被省略。
如果一个Client Program
遇到一个模棱两可的路径,它的行为将是未定义的。
设备树中的每个结点都有属性来描述结点的特性。属性由键值对名字和值组成。
属性名
属性名由表2.2中字符组成的长为1~31的字符串。
表2.2 属性名的有效字符表
字符 | 0 - 9 | a - z | A - Z | , | . | _ | + | - | ? | # |
---|---|---|---|---|---|---|---|---|---|---|
描述 | 数字 | 小写字母 | 大写字母 | 逗号 | 小数点 | 下滑线 | 加号 | 破折号 | 问号 | #号 |
非规范的属性名应该有一个唯一的字符前缀,像具有辨识度的公司或组织名来定义属性。例如:
fsl,channel-fifo-len
ibm,ppc-interrupt-server#s
linux,network-index
属性值
属性值是一个包含属性相关信息的数组。如果它表达的是true-false信息,那么它可能是一个空值。在这个案例中,详细的描述了属性的缺省性(有/无)。
表2.3:属性值
值 | 描述 |
---|---|
<empty> | 值是empty。用来表示这个属性它自己是否存在的真假(true-false)信息。 |
<u32> | big-endian格式的32位整数。例如32位值 0x11223344 在内存中的形式为: |
address 11 | |
address+1 22 | |
address+2 33 | |
address+3 44 | |
<u64> | big-endian格式的64位整数,它由两个<u32>组成。例如0x1122334455667788将被表示为2个单元:<0x11223344 0x4455667788> 它在内存中的形式为: |
address 11 | |
address+1 22 | |
address+2 33 | |
address+3 44 | |
address+4 55 | |
address+5 66 | |
address+6 77 | |
address+7 88 | |
<string> | 字符串是可打印的字符(不能是空格等)。例如"hello"它在内存中的形式为: |
address 'h' | |
address+1 'e' | |
address+2 'l' | |
address+3 'l' | |
address+4 'o' | |
address+5 '\0' | |
<stringlist> | 由多个<string>组成的字符串列表。如"hello","world",他在内存中的形式为: |
address 'h' | |
address+1 'e' | |
address+2 'l' | |
address+3 'l' | |
address+4 'o' | |
address+5 '\0' | |
address+6 'w' | |
address+7 'o' | |
address+8 'r' | |
address+9 'l' | |
address+10 'd' | |
address+11 '\0' |
DTSpec描述了一个设备结点的标准属性集合。在这章将进行这些属性的说明。DTSpec(见第三章)设备结点的定义可能对关于标准属性的使用有另外的要求和约束。第四章中特定设备的表示也有一些具体的额外要求。
注意: 在本文档中所有设备树结点的示例中对其结点和属性的描述都使用DTS(Devicetree Source)格式。
属性名:compatible
值类型:<stringlist>
描述:
compatible
属性值由一个或多个字符串组成,为设备定义了规范的编程模式。这个字符串列表应该是被client program的设备驱动程序所选择使用。属性值由一系列以null结尾的字符串组成并且从左到右为具体到一般,即左边的字符串的含义为右边的子集。他们允许一个设备用一个系列的设备去表达其兼容性,可能允许单个设备驱动去匹配多个设备。
推荐的格式是"manufacturer,model",这里的manufacturer
是一个描述制造商的字符串(例如股票代号)并且model
表明了对应的型号。
举例:
compatible = "fsl,mpc8641", "ns16550";
在这个例子中一个操作系统将先去查找支持fsl,mpc8641
的设备驱动。如果没有找到,它将继续查找支持更通用的ns16550
设备类型的驱动程序。
属性名:model
值类型:<string>
描述:
model
属性值是一个描述制造商设备型号的字符串。
推荐的格式是"manufacturer,model"。manufacturer
是一个描述制造商的字符串(例如股票代号)并且model
表明了对应的型号。
举例:
model = "fsl,MPC8349EMITX"
属性名:phandle
值类型:<u32>
描述:
phandle
属性是结点在设备树中的唯一标识(id)。通常它的值被其他结点使用,来表示对它的引用。
举例:
观察下面的devicetree的截取部分:
pic@10000000 {
phandle = <1>;
interrupt-controller;
};
phandle的值是1。另外一个设备结点能够用phandle的值引用pic结点。
another-device-node {
interrupt-parent = <1>;
};
注意:老的版本可能不同,包含这个属性不同的形式
linux,phandle
。为了兼容性,如果phandle
不存在,用户程序可能想支持linux, phandle
。这意味着这连个属性的使用是相同的。
注意: 大多在DTS中的devicetrees(看附录A)不包含显式的phandle属性。DTC工具会在DTS编译为DTB时候自动插入phandle属性。
属性名:status
值类型:<string>
描述:
status
属性表示一个设备的操作状态。有效值如下表2.4。
表2.4:status属性值
值 | 描述 |
---|---|
"okay" | 设备是可操作状态 |
"disabled" | 表明当前不可操作,但未来可能变成可操作的(例如:一些没插入或未关闭)。特定设备的disabled 情参考设备绑定 |
"reserved" | 表明设备可操作但不应该使用。典型的是设备的使用是通过其他软件组件控制的,如平台固件 |
"fail" | 表明设备不可操作。探测到设备出错并不可能修复变成可操作状态 |
"fail-sss" | 同上,并sss 表明错误条件被检测到 |
属性名:#address-cells
,#size-cells
值类型:<u32>
描述:
#address-cells
,#size-cells
属性可能被使用在设备树层次结构和描述孩子结点怎样被寻找且有孩子的结点中。#address-cells
属性定义了<u32> 单元用于表示在孩子结点的reg
属性的地址, #size-cells
表示其大小。
#address-cells
,#size-cells
属性不能从祖先结点继承,他们应该显示定义。
一个DTSpec-compliant boot程序应该在所有孩子的结点提供#address-cells
和#size-cells
。
如果没有提供,程序应该假定#address-cells
为默认值2,#size-cells
默认值为1。
举例:
soc {
#address-cells = <1>;
#size-cells = <1>;
serial@4600 {
compatible = "ns16550";
reg = <0x4600 0x100>;
clock-frequency = <0>;
interrupts = <0xA 0x8>;
interrupt-parent = <&ipic>;
};
};
例子中soc结点中#address-cells
,#size-cells
都设置为1。这代表要求用一个(<32>)单元表明地址和大小。
其中在soc结点中的serial设备的reg
属性必须遵守这个规定-----用一个单元(0x4600)表示地址和用一个单元(0x100)表示大小
属性名:reg
属性值:<prop-encoded-array>
把 (address, length) '键值对'编码/组成数组。
描述:
reg
属性描述的是挂载在总线上的设备资源地址。通常表示IO寄存器块内存映射的偏移地址和长度,但在一些总线类型上可能有不同的含义。root结点在地址空间中定义的地址是CPU实地址。
它的值是<prop-encoded-array>
,由地址和长度的'键值对'组成,<address, length>
。其中address
和length
是由总线指定的以<32u>
类型为单元/位?的数据,并且是由该设备结点的父结点中 #address-size
#size-cells
属性来描述。如果父结点中#size-cells
的值是0,那么reg
属性中的 length
域应该被省略。
举例:
假设一个设备在片上系统上有两个寄存器块,它们在SOC上的偏移地址和大小分别为(0x3000, 0x20)
, (0xFE00 0x100)
。这reg
属性将被编码成如下形式(假设#address-size
#size-cells
的值都是1):
reg = <0x3000 0x20 0xFE00 0x100>
属性名:virtual-reg
值类型:<u32>
描述:
virtual-reg
描述的是映射到设备节点reg
属性中的第一个物理地址的有效地址。这个属性使能了 boot 程序对 client 程序虚拟地址到物理地址的映射的建立。
属性名:ranges
值类型:<empty>
或 <prop-encoded-array>
编码成(child-bus-address,parent-bus-address,length)
形式的三元组
描述:
ranges
属性表示的是总线地址空间和其父地址空间的映射或转化。
其属性的值的格式为三元组(child-bus-address,parent-bus-address,length)
,值是任意数。
-
child-bus-address
是在子总线地址空间的物理地址。对于当前地址单元的值是总线依赖的,并且能从这节点的#address-cells
属性中确定(现式ranges
属性的节点)。 -
parent-bus-address
是父总线地址空间的物理地址。总线依赖且可以从定义parent-bus-address
节点中的address-cells
属性确定 -
length
是子地址空间范围的长度,能中当前节点的size-cells
属性确定。
如果该属性被定义为<empty>
,则表明父地址空间和孩子地址空间是一样的,并且没有地址转换要求。
如果这个属性在一个总线节点中不存在,表明没有地址空间映射存在。
地址转换例子:
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>;
};
};
soc节点的range属性的值是<0x0 0xe0000000 0x00100000>
;
它描述了一个1024k大小的地址空间,从孩子节点的物理地址0x0映射到父物理地址0xe0000000。通过映射,serial设备节点能加载或存储(load or store)访问地址0xe0004600(通过在ranges中的映射的0xe0000000加上0x4600的偏移来寻址)。
属性名:dam-ranges
值类型:<empty>
或 <prop-encoded-array>
编码成(child-bus-address,parent-bus-address,length)
形式的三元组
描述:
dam-ranges
属性通常是描述一个内存总线映射的DMA结构,设备书的上级能被来自总线的DMA操作访问。它提供了在总线和其父(节点)之间的物理地址转换。
这个属性值的格式是一个任意数字的三元组(child-bus-address,parent-bus-address,length)
。每个三元组描述了一个相邻的DMA地址范围。三元组的元素与属性ranges
的功能类似。
DTSpec 兼容当前OFRP:Interrupt Mapping,Version 0.9 中的中断树模型。一个设备树存在一个逻辑中断树来表示平台硬件的层次和路由。虽然通常说其是一个中断树,跟严格的说是一个有向无环图。
对于一个中断控制器的中断源的物理线在设备树中是由属性interrupt-parent
来表示。表示中断生成设备的节点包含interrupt-parent
属性,该属性有一个phandle值,指向中断路由到的设备,通常是一个中断控制器。如果一个中断生成设备没有interrupt-parent
属性,那么会假设他中断的父节点是它的设备树的父节点。
每个中断生成设备,包含一个interrupt
属性,用一个值来描述这个设备的一个或多个中断源。每个中断源都用称为中断描述符的信息表示。中断说明符的格式和含义是特定于中断域的,它是取决于中断域根节点上的属性。#interrupt-cells
属性由中断域的根用来定义中断说明符所需的<u32>
值的数量。例如,对于开放式PIC中断控制器,中断说明符合采用两个32位值,由中断号和中断的级别/检测信息组成。
中断域是解释中断说明符的上下文。域的根是中断控制器或中断连接。
- 中断控制器控制器是一个物理设备,需要一个驱动程序来处理由它路由的中断。它也可能级联到另一个中断域。中断控制器是由设备树该节点上的
interrupt-controller
属性指定的。 - 中断连接定义了一个中断域和另一个中断域的转换。翻译是基于具体域和具体中线信息的。域之间的转换是通过属性
interrupt-map
完成的。例如,PCI控制器设备节点可能是一个中断连接,它定义了从PCI中断命名空间(INTA,INTB,等)到带有中断请求(IRQ)号的中断控制器的转换。
当中断树遍历到一个没有interrupt
属性且没有显式的父节点的中断控制器节点时,这中断树的根节点将被确定。
图2.3显示了中断父关系的设备树的图表示。它显示了设备树的自然结构以及每个节点在逻辑中断树中的位置。
在图2.3中:
-
中断树的根节点是
open-pic
中断控制器。 -
中断树根节点有三个孩子节点--直接路由他们的中断到
open-pic
- device1
- PCI host controller
- GPIO Controller
-
存在三个中断域;一个根节点是
open-pic
,一个根节点是PCI host bridge
和一个根节点是GPIO Controller
。 -
两个连接节点,
PCI host bridge
和GPIO controller
。
interrupts
属性:interrupts
值类型:<prop-encoded-array>
编码为任意数量的中断说明符
描述:
设备节点的interrupts
属性定义了设备生成的一个或多个中断。该属性的值友任意多个中断描述符组成。中断描述符的格式由中断域的根的绑定定义的。
interrupts
会被interrupts-extended
属性覆盖,通常只应用其中一个
例子:
通常在一个PIC兼容中断域中中断描述符的定义是由两个单元组成--一个中断号和电平/检测信息。如下面的例子,定义了一个中断描述符,其中包括一个中断号0xA和电平/检测编码为8。
interrupts = <0xA 8>;
interrupt-parent
属性:interrupt-parent
值类型:<phandle>
描述:
因为在中断树中节点的层级可能不匹配设备树,interrupt-parent
属性可用于显示定义中断父节点。它的值是父级的phandle。如果一个设备中没有该属性,将默认它设备树的父节点为其在中断树中的父级。
interrupts-extended
属性:interrupts-extended
值类型:<phandle>
prop-encoded-array
描述:
属性interrupts-extended
属性列出了设备生成的中断。当一个设备连接多个中断控制器时,应该使用interrupts-extended
而不是interrupts
属性,因为它用每个中断描述符对父节点phandle进行编码。
例子:
这个例子将展示怎样使用interrupts-extended
属性描述一个设备两个中断输出连接到不同的中断控制器的描述。pic
是#interrupt-cells
为2的中断控制器,gic
是#interrupt-cells
为1的中断控制器。
Interrupts-extended = <&pic 0xA 8>, <&tic 0xda>;
interrupts
和 interrupts-extended
属性是相互独立的。一个设备应该只使用其中一个。只有当需要与不了解interrupt-extended
的软件兼容时,才允许同时使用这两种方法。如果同时存在interrupts-extended
和interrupts
,则interrupts-extended
优先。
#interrupt-cells
属性:#interrupt-cells
值类型:<u32>
描述:
#interrupt-cells
属性描述了中断域中中断描述符单元数量的定义。
interrupt-controller
属性:interrupt-controller
值类型:<empty>
描述:
存在interrupt-controller
属性的节点为中断控制器节点。
一个中断级联节点应该包含#interrupt-cells
属性。
interrupt-map
属性:interrupt-map
值类型:<prop-encoded-array>
编码为任意数量的中断映射项
描述:
中断映射是nexus节点上的一个属性,它将一个中断域与一组父中断域连接起来,并指定如何将子域中的中断说明符映到各自的父域。
中断映射是一个表,其中每一行都是一个映射条目,由五部分组成:子单元地址、子中断说明符、中断父级、父单元地址、父中断说明符。
- 子单元地址:子节点被映射的地址。其所需的32位单元数由子节点所在的总线节点的
#address-cells
属性描述。 - 子中断描述符:子节点被映射的中断描述符。其32bit的值是由该节点的
#interrupt-cells
属性描述--该节点是包含interrupt-map
属性的级联节点。 - interrupt-parent:一个
<phandle>
值,指向子域映射到的中断父级 - 父单元地址:中断父级域中的单元地址。该地址的32位单元数是由中断父字段指向的节点的
#address-cells
属性描述。 - 父中断说明符:父域中的中断说明符。该32位单元数由中断父字段所指向节点的
#interrupt-cells
属性描述。
在中断映射表上使用unit-address
/中断描述符对与中断映射中的子部分相匹配,在中断映射表上执行查找。由于单元中断说明符中的某些字段可能不相关,因此在查找完成之前会应用掩码。这掩码定义在interrupt-map-mask
属性中。
注意:子节点和父级节点是要有
#address-cells
和interrupt-cells
属性定义的。如果一个单元地址部分没有被要求,#address-cells
应该显示定义为0。
interrupt-map-mask
属性:interrupt-map-mask
值类型:<prop-encoded-array>
作为位掩码
描述:
一个interrupt-map-mask
属性在中断树中是对级联节点的描述。该属性是用于中断映射属性中指定的表中,查找的传入单元中断说明符。
#interrupt-cells
属性:#interrupt-cells
值类型:<u32>
描述:
#interrupt-cells
属性定义了中断域,编码中断说明符所需的单元数。
下面显示了PCI总线控制器和对两个PCI 槽(slots) (IDSEL, 0x11, 0x12) 的中断映射描述 的设备树片段。其中slots槽1和2的 INA,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 */
>;
};
};
一个Open PIC中断控制器通过中断控制器的标识interrupt-controller
属性被表示。
interrupt-map表中的每行由五部分组成:子单元地址和中断描述符,映射到具有父单元地址和中断说明符的中断父节点。
- 例如:interrupt-map表的第一行描述了slot 1的INTA的映射。这行的结构如下:
- 子单元地址:0x8800 0 0
- 子中断描述符:1
- 中断父节点:&open-pic
- 父单元地址:空(因为open-pic节点中
#address-cells = <0>
)- 子单元地址是<0x8800 0 0 >。该值通过PCI中断控制器的
#address-cells
属性(值为3)的值确定的 由3个32位单元表示。 - 子中断描述符号是<1>,它指定PCI绑定所描述的INTA。由子中断域PCI中断控制器的
interrupt-cells
属性(值是1)所指定为一个32位单元。 - 中断父级/节点由指向slot父级的phandle指定,即Open PIC中断控制器
- 这父级没有断元地址。应为父中断域中(open-pic节点)
#address-cells
的值是0. - 父中断描述符是<2 1>。由父节点opne-pic中的
#interrupt-cells
确定为2个单元表示。(<2 1>
是由绑定的Open PIC中断控制器指定(见章节4.5)。值<2>指定INTA连接到中断控制器上的物理中断源号。值<1>指定级别/sense编码)。
- 子单元地址是<0x8800 0 0 >。该值通过PCI中断控制器的
在这个例子中,属性interrupt-map-mask
属性值为<0xf800 0 0 7>
. 在interrupt-map
表执行查询前,这个mask作为子单元中断描述符。
查找IDSEL 0x12 (slot 2)的INTB的open-pic中断源编号(功能0x3),将会执行以下步骤:
-
子单元地址和中断描述符形成了
<0x9300 0 0 2>
.- 地址编码包括总线号(0x0 << 16),设备号(0x12 << 11),功能号(0x3 << 8)。
- 中断说明符是2,是根据PCI绑定的INTB号而得。
-
应用
interrupt-map-mask
的值<0xf800 0 0 7>
,得到<0x9000 0 0 2>
. -
该结果在中断映射表中查询,该表映射到父中断说明符
<4 1>
.
级联节点有一个#<specifier>-cells
属性,其中是描述符空间。例如,'gpio', 'clock', 'reset', 等。
属性:<specifier>-map
值类型:<prop-encoded-array>
,任意数量的说明符合映射项。
描述:
<specifier>-map
是级联节点的一个属性,它将一个说明符域与一组父说明符域相连。并在子域中描述是怎样被映射到他们的父域的。
这个map是一个表,每行由 子说明符, 说明符父级,父说明符组成的映射项。
子说明符: 被映射的子节点说明符。它的32bit单元是由节点中的#<specifier>-cells
属性决定(该节点是存在中<specifier>-map
属性的级联节点).
描述符父级: 一个<phandle>
的值表示描述符父级到孩子域的映射。
父级描述符: 父域的描述符。描述符父节点中一个32bit大小的#<specifier>-cells
属性来描述这个部分。
可以通过匹配描述符于映射的子描述符在映射表上进行查找操作。因为在描述符中的一些属性/域可能无关的或需要修改的,所以在查询前会先使用一个掩码Mask。这个Mask被定义在<specifier>-map-mask
属性中。
类似的,当描述符被映射时,在单位描述符中的一些属性需要保证不变的从子节点传递到父节点。对于这种情况,可以使用<specifier>-map-pass-thru
属性(见2.5.1.3节)将掩码应用于子描述符,并能复制与父单位描述符匹配的任何位。
属性:<specifier>-map-mask
值类型:<prop-encoded-array>
做为位掩码
描述:
可以给级联节点设置该属性。这个属性描述了应用在<specifier>-map
属性指定的表中查找的子节点说明符的掩码。在子节点描述符所有相应的位会覆盖其父节点相应的位。如果没有指定该属性,将会默认掩码全0。
属性:#<specifier>-cells
值类型:<32>
描述:
该属性定义了一个域说明符编码所要求的单元数。
下面为设备树中有代表性的片段--两个GPIO控制器和一个用于描述两个控制器上的几个GPIO通过板上的连接器到设备的GPIO路由的示例说明符。扩展设备节点位和带有连个GPIO控制器的SoC分别位于连接器的两侧。
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_gpio1 4 0>,
<2 0 &soc_gpio1 3 0>,
<3 0 &soc_gpio1 2 0>;
gpio-map-mask = <0xf 0x0>;
gpio-map-pass-thru = <0x0 0x1>;
};
expansion_device {
reset-gpios = <&connector 2 GPIO_ACTIVE_LOW>;
};
gpio-map 表的每一行由三部分组成:子节点描述符用父节点映射到gpio-connector节点。
- 例如,这描述符映射表的第一行描述了对链接器GPIO 0的映射。这行的组成如下:
- 子描述符:0 0
- 描述符父节点:&soc_gpio1
- 父描述符:1 0
- 子描述符
<0 0>
,它指定了连接器中的GPIO 0 的标志字段为 0. - 描述符父级是通过phandle指向连接器的描述符父级--在SoC中的第一个GPIO控制器
- 父描述符是
<1 0>
.表示gpio说明符的单元数是由描述符的父级节点--soc_gpio1 中的#gpio-cells
属性确定的。其中<1 0>
是由GPIO控制器的设备绑定指定的。<1>
指定GPIO控制器上的GPIO引脚号,连接器上的GPIO 0连接到该GPIO控制器。值<0>
表示标志(低有效,高有效,等)。
- 子描述符
在这个例子中,gpio-map-mask
属性的值是<0xf 0>
.这mask在执行查找(在gpio-map中)之前用于子节点描述符,gpio-map-pass-thru
属性的值为<0x0 0x1>
.当映射它到父节点描述符时应用到子节点描述符。此掩码中设置的任何位都会从父节点描述符中清除,并从子单位说明符复制到父单位描述符。
下面的步骤描述了,从扩展设备的reset-gpio
属性中查找GPIO 2的连接器描述符源编号的过程:
- 子描述符值形式为<2 GPIO_ACTIVE_LOW>
- 这个描述符把每个这GPIO的binding设置为低电平有效
gpio-map-pass-thru
中的值<0xf 0x0>
和 子描述符进行与运算,得到<0x2 0>
- 在
gpio-map
中查询结果,该表映射到父描述符<3 0>
和&soc_gpio1
的phandle。 gpio-map-pass-thru
的值翻转并且和gpio-map表中的符描述符进行与运算,结果为<3 0>
.子节点描述符和gpio-map-pass-thru
掩码进行与运算,形如<0 GPIO_ACTIVE_LOW>
然后和清除后的父描述符<3 0>
进行或运算,结果为<3 GPIO_ACTIVE_LOW>
。- 描述符
<3 GPIO_ACTIVE_LOW>
附加到被映射的phandle&soc_gpio1
,结果为<&soc_gpio1 3 GPIO_ACTIVE_LOW>
.