文章目录
本文主要介绍如何为新机器编写设备树,它旨在描述设备树的基本概念以及它们如何将其应用于描述机器。有关设备树数据格式的完整技术说明,请参阅 ePAPR v1.1规范。ePAPR规范比本文介绍的有关设备树的描述包含更多详细的信息,请参阅此文以获取本文未涵盖的关于设备树的更高级用法 。
基本数据格式
设备树是节点和属性的简单树型结构。属性是键-值对,节点可以包含属性和子节点。下面的代码是设备树的结构模板,可以先了解一下:
/ DTS-V1 /; / { node1 { a-string-property =“A string”; a-string-list-property =“first string”,“second string”; //十六进制隐含在字节数组中。不需要'0x'前缀. a-byte-data-property = [01 23 34 56];
child-node1 { //boolean,first-child-property定义为true,不定义为false. first-child-boolean-property; second-child-cell-property = <1>; a-string-property =“Hello,world”; }; child-node2 { }; }; node2 { an-empty-property; a-cell-property = <1 2 3 4>; };
};
这棵树显然没用,因为它没有描述任何东西,但它确实显示了节点和属性的结构。既:
- 单个根节点:“ / ”
- 几个子节点:“ node1 ”和“ node2 ”
- node1的几个孩子:“ child-node1 ”和“ child-node2 ”
- 一堆散落在树上的属性。
属性是简单的键值对,其中,值可以为空或包含任意字节流。虽然数据类型未编码到数据结构中,但有一些基本数据表示可以在设备树源文件中表示。
- 文本字符串(以null结尾)用双引号表示:
string-property = “a string”;
- 'Cells’是由尖括号分隔的32位无符号整数:
cell-property = <0xbeef 123 0xabcd1234>;
- 二进制数据用方括号分隔:
binary-property = [0x01 0x23 0x45 0x67];
- 可以使用逗号将不同表示的数据连接在一起:
mixed-property = “a string”, [0x01 0x23 0x45 0x67], <0x12345678>;
- 逗号还用于创建字符串列表:
string-list = “red fish”, “blue fish”;
基本概念
要了解设备树的使用方式,最好的方式就是从头构建一棵。下面,我们就从一台简单的机器开始,去逐步构建一棵设备树来描述它。
样机
考虑以下想象的机器(松散地基于ARM Versatile),由“Acme”制造并命名为“Coyote’s Revenge”:
- 单核 32位ARM处理器
- 处理器本地总线连接到内存映射串行端口,spi总线控制器,i2c控制器,中断控制器和外部总线桥
- 1个基地址为0的256MB SDRAM
- 2个基于0x101F1000和0x101F2000的串行端口
- 1个基于0x101F3000GPIO控制器
- 1个基于0x10170000的SPI控制器,具有以下器件:
- 带有SS引脚的MMC插槽连接到GPIO#1
- 外部总线桥接器具有以下设备:
- SMC SMC91111以太网设备连接到外部总线,基于0x10100000
- i2c控制器基于0x10160000,具有以下设备: Maxim DS1338实时时钟。响应从站地址1101000(0x58)
- 基于0x30000000的64MB NOR闪存
初始结构
第一步是为机器设置骨架结构。这是有效设备树所需的最小结构。在此阶段,您需属性compatible来唯一标识机器。
/ DTS-V1 /;
/ {
compatible =“acme,coyotes-revenge”;
};
- 1
- 2
- 3
- 4
- 5
compatible 指定系统的名称。它包含一个“,形式的字符串。重要的是指定确切的设备,并包含制造商名称以避免命名空间冲突。由于操作系统将使用该compatible值来决定选择何种架构来启动机器运行,所以将正确的数据放入此属性非常重要。从理论上讲,兼容性是操作系统唯一识别机器所需的所有数据。如果所有机器细节都是硬编码的,那么操作系统可能只需要包含“acme,coyotes-revenge” 的compatible属性。
CPU
下一步是描述每个CPU。为每个CPU添加一个名为“cpus”的容器节点,其中包含一个子节点。下面描述的处理器平台是双核Cortex A9。
/ DTS-V1 /; / { compatible =“acme,coyotes-revenge”; cpus { cpu @ 0 { compatible =“arm,cortex-a9”; }; cpu @ 1 { compatible =“arm,cortex-a9”; }; }; };
每个cpu节点中的兼容属性是一个字符串,它指定表单中的确切cpu模型 , ,就像顶层的兼容属性一样。
稍后将向cpu节点添加更多属性,但我们首先需要讨论更多的基本概念。节点名称
值得花点时间谈谈命名约定。每个节点必须在表单中有一个名称 [@ ]。 是一个简单的ascii字符串
最多可以包含31个字符。通常,节点根据它代表的设备类型命名。即,3com以太网适配器的节点将使用名称ethernet ,而不是3com509。如果节点描述的是具有地址的设备,则需要包括单元地址信息。通常,单元地址是用于访问设备的主要地址,并列在节点的 reg 属性中表示出来。我们将在本文档后面介绍reg属性。
同级节点必须是唯一命名的,这里说的节点名称是name和unit-address,name是可以系统的,但只要地址不同(比如,serial@101f1000和serial@101f2000)就不会有问题。
有关节点命名的完整详细信息,请参阅ePAPR规范的第2.2.1节。
设备
系统中的每个设备都由设备树节点表示。下一步是使用每个设备的节点填充树。现在,新节点将保持为空,直到我们可以讨论如何处理地址范围和irq。
/ DTS-V1 /; / { compatible =“acme,coyotes-revenge”; cpus { cpu @ 0 { compatible =“arm,cortex-a9”; }; cpu @ 1 { compatible =“arm,cortex-a9”; }; };
serial@101F0000 { compatible =“arm,pl011”; }; serial@101F2000 { compatible =“arm,pl011”; }; gpio@101F3000 { compatible =“arm,pl061”; }; interrupt-controller@ 10140000 { compatible =“arm,pl190”; }; spi@10115000 { compatible = "arm,pl022"; }; external-bus { ethernet@0,0 { compatible =“smc,smc91c111”; }; i2c@1,0 { compatible =“acme,a1234-i2c-bus”; rtc @ 58 { compatible =“maxim,ds1338”; }; }; flash @ 2,0 { compatible =“samsung,k8f1315ebm”,“cfi-flash”; }; };
};
在此树中,已为系统中的每个设备添加了一个节点,层次结构反映了设备连接到系统的方式。即,外部总线上的设备是外部总线节点的子设备,i2c设备是i2c总线控制器节点的子设备。通常,层次结构是从CPU的角度表示的系统视图。此树在此时无效。它缺少有关设备之间连接的信息。该数据将在稍后添加。
在这棵树中要注意的一些事情:
- 每个设备节点都有一个 compatible 属性。
- flash节点在兼容属性中有2个字符串。请继续阅读下一节以了解原因。
- 如前所述,节点名称反映了设备的类型,而不是特定的模型。有关应尽可能使用的已定义通用节点名称列表,请参阅ePAPR规范的第2.2.2节。
了解 compatible Property
树中表示设备的每个节点都需要具有compatible 属性。compatible是操作系统用来决定绑定设备和设备驱动程序的
关键。compatible 是一个字符串列表。列表中的第一个字符串指定节点在表单中表示的确切设备","。剩余的字符串表示设备兼容的其他设备。
例如,飞思卡尔MPC8349片上系统(SoC)具有串行器件,该器件实现了National Semiconductor ns16550寄存器接口。因此,
MPC8349串行设备的兼容属性应为: compatible = “fsl,mpc8349-uart”, “ns16550” 。在这种情况下,fsl,mpc8349-uart 指定确切的器件,并用ns16550 声明它与National Semiconductor 16550 UART寄存器级兼容。
注意: ns16550 由于历史原因,没有制造商前缀。所有新的兼容值都应使用制造商前缀。这种做法允许将现有设备驱动程序绑定到较新的设备,同时仍然唯一地标识确切的硬件。
警告:不要使用通配符兼容值,例如“fsl,mpc83xx-uart”或类似值。半导体供应商总是会做出改变,在改变它的时候为时已晚,打破了你的通配符假设。相反,选择特定的半导体实现并使所有后续芯片与之兼容。
寻址如何工作
可寻址的设备使用以下属性将地址信息编码到设备树中:
- reg
- #address-cells
- #size-cells
每个可寻址设备获取一个 reg ,其结构为元组列表,形如 reg = <address1 length1 [address2 length2][address3 length3] … > 。每个元组表示设备使用的地址范围。每个地址值是一个或多个称为单元的32位整数的列表。
类似地,长度值可以是单元格列表,也可以是空的。
由于地址和长度字段都是可变大小的变量,因此父节点中的 #address-cells 和 #size-cells 属
性用于表示每个字段中有多少个单元格。或者换句话说,正确解释reg属性需要父节点的#
address-cells和#size-cells值。要了解这一切是如何工作的,我们可以从CPU开始,将寻址属性添
加到示例设备树中。
CPU寻址
在讨论寻址时,CPU节点信息是最简单的一种情况。为每个CPU分配一个唯一的ID,并且没有与CPU
ID相关联的大小。
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu @ 0 {
compatible =“arm,cortex-a9”;
reg = <0>;
};
cpu @ 1 {
compatible =“arm,cortex-a9”;
reg = <1>;
};
};
在cpus节点中, #address-cells设置为1,#size-cells设置为0。这意味着子reg值是单个
uint32,并且没有大小字段的地址。在这种情况下,两个cpus被分配地址0和1。#size-cells 对
于cpu节点是0,因为每个cpu仅被分配一个地址。
您还会注意到该 reg 值与节点名称中的值匹配。按照惯例,如果节点具有reg属性,则节点名
称必须包含unit-address,这是reg属性中的第一个地址值。
内存映射设备
与在cpu节点中的单个地址值不同,内存映射设备被分配了一系列地址空间,内存设备的所有操作都被映射到该地址空间中。 #size-cells用于表示每个子reg元组中长度字段的大小。在以下示例中,每个地址值为1个单元(32
位),每个长度值也为1个单元,这在32位系统上是典型的。对于#address-cells和#size-cells,
64位机器可以使用值2来获得设备树中的64位寻址。
/ DTS-V1 /; / { #address-cells = <1>; #size-cells = <1>; ...
serial @ 101f0000 { compatible =“arm,pl011”; reg = <0x101f0000 0x1000>; }; serial @ 101f2000 { compatible =“arm,pl011”; reg = <0x101f2000 0x1000>; }; gpio @ 101f3000 { compatible =“arm,pl061”; reg = <0x101f3000 0x1000 0x101f4000 0x0010>; }; interrupt-controller@ 10140000 { compatible =“arm,pl190”; reg = <0x10140000 0x1000>; }; spi@10115000 { compatible = "arm,pl022"; reg = <0x10115000 0x1000 >; }; ......
};
为每个设备分配一个基址,并为其分配区域的大小。本例中的GPIO设备地址分配了两个地址范围;
0x101f3000 … 0x101f3fff和0x101f4000…0x101f400f。一些设备存在于具有不同寻址方案的总线上。例如,可以使用分立的芯片选择线将器件连接到外部总线。由于每个父节点为其子节点定义寻址域,因此可以选择地址映射以最好地描述系统。下
面的代码显示了连接到外部总线的设备的地址分配,芯片选择号编码到地址中。
external-bus{
#address-cells = <2>;
#size-cells = <1>;
ethernet @ 0,0 {
compatible =“smc,smc91c111”;
reg = <0 0 0x1000>;
};
i2c @ 1,0 {
compatible =“acme,a1234-i2c-bus”;
reg = <1 0 0x1000>;
rtc @ 58 {
compatible =“maxim,ds1338”;
};
};
flash @ 2,0 {
compatible =“samsung,k8f1315ebm”,“cfi-flash”;
reg = <2 0 0x4000000>;
};
};
external-bus用了2个cells定义地址值:一个用于芯片的片选,一个用于表示相对于被选芯片的基址偏
移。长度字段保持为单个cell,因为只有地址的偏移部分需要具有范围。因此,在这个例子
中,每个reg条目包含3个单元格;芯片的片选号,偏移量和长度。
由于地址域包含在节点及其子节点中,因此父节点可以自由定义对总线有意义的任何寻址方案。
直接父节点和子节点之外的节点通常不必关心本地寻址域,并且必须映射地址以从一个域到另一
个域。
非内存映射设备
其他设备未在处理器总线上的映射内存。它们可以具有地址范围,但CPU无法直接访问它们。相
反,父设备的驱动程序将代表CPU执行间接访问。
以i2c设备为例,每个设备都分配了一个地址,但没有与之关联的长度或范围。这看起来与CPU地
址分配大致相同。
i2c @ 1,0 {
compatible =“acme,a1234-i2c-bus”;
#address-cells = <1>;
#size-cells = <0>;
reg = <1 0 0x1000>;
rtc @ 58 {
compatible =“maxim,ds1338”;
reg = <58>;
};
};
};
有些事情需要注意:
-
机器有只有一个主中断控制器,中断控制器@10140000, 可以存在多个从中断控制器,例如,gpio0 @ 101f3000、gpio1 @ 101f5000等,其与主中断控制形成级联关系。
-
标签’intc:'已添加到中断控制器节点,标签用于将phandle分配给根节点中的interrupt-parent属性。此interrupt-parent为系统的默认值,因为除非显式覆盖它,否则所有子节点都会继承它。
-
每个器件都使用interrupt属性来指定不同的中断输入线(interrupt input line)。
-
#interrupt-cells为2,因此每个中断说明符都有2个cells。此示例使用第一个cell编码设备所使用的中断号,第二个cell用于编码中断属性标志,例如高电平触发还是低电平触发,或边沿触发亦或是电平敏感触发。对于任何给定的中断控制器,请参阅控制器的绑定文档以了解如何编码interrupt specifier。
设备特定数据
除了公共属性之外,还可以向节点添加任意属性和子节点。只要遵循一些规则,就可以添加操作系统所需的任何数据。
-
首先,新的特定于设备的属性名称应使用制造商前缀,以便它们不会与现有的标准属性名称冲突。
-
其次,必须在绑定中记录属性和子节点的含义,以便设备驱动程序作者知道如何解释数据。绑定文档描述特定兼容值的含义,其描述:它应具有的属性,可能具有的子节点以及它所代表的设备。每个唯一 compatible 值应具有自己的绑定(或声明与另一个兼容值的兼容性)。此Wiki中记录了新设备的绑定。有关文档格式和审阅过程的说明,请参见主页
-
第三,在devicetree-discuss@lists.ozlabs.org邮件列表上发布新的绑定以供审核。检查新绑定会捕获许多常见错误,这些错误将在未来引发问题。
特殊节点
aliases 节点
特定节点通常由完整路径引用 /external-bus/ethernet@0,0 ,但是当用户真正想知道的是“哪个设备是eth0?”时,这会很麻烦。aliases 节点可用于为完整设备路径分配短别名。例如:
aliases{ ethernet0 = ð0; serial0 = &serial0; };
-
PCI主桥
本节介绍Host/PCI bridge节点。
注意,本节假设了一些PCI的基本知识。这不是关于PCI的教程,如果您需要更深入的信息,
请阅读 。您还可以参考 ePAPR v1.1 或PCI Bus Binding to Open Firmware。可在此处找到飞思卡尔MPC5200的完整工作示例。
PCI总线编号
每个PCI总线段都是唯一编号的,并且使用 bus-ranges 在pci节点中公开总线编号,bus-ranges包含两个cells单元。第一个cell给出分配给该节点的总线编号,第二个cell给出任何从属PCI总线的最大总线编号。
样机具有单个pci总线,因此两个单元都为0。
pci @ 0x10180000 {
compatible = “arm,versatile-pci-hostbridge”,“pci”;
reg = <0x10180000 0x1000>;
interrupts = <8 0>;
bus-ranges = <0 0>;
};
PCI地址转换
与前面描述的本地总线类似,PCI地址空间与CPU地址空间完全分离,因此需要进行地址转换才能从PCI地址转换到CPU地址。一如往常,这是使用完成range, #address-cells 和 #size-cells属性。
pci @ 0x10180000 {
compatible =“arm,versatile-pci-hostbridge”,“pci”;
reg = <0x10180000 0x1000>;
interrupts = <8 0>;
bus-ranges = <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 >;
};
如您所见,子地址(PCI地址)使用3个cells,PCI范围编码为2个cells。第一个问题可能是,为什么我们需要三个32位cells来指定PCI地址。这三个cells分别表示为:phys.hi,phys.mid和phys.low。
- phys.hi cell: npt000ss bbbbbbbb dddddfff rrrrrrrr
- phys.mid cell: hhhhhhhh hhhhhhhh hhhhhhhh hhhhhhhh
- phys.low cell: llllllll llllllll llllllll llllllll
PCI地址为64位宽,并编码为phys.mid和phys.low。然而,真正有趣的事情是在phys.high,这是一
个有位域:
- n :可重定位区域标志(此处不起作用)
- p :prefetchable(可缓存)区域标志
- t :别名地址标志(此处不起作用)
- ss :空间代码
- 00:配置空间
- 01:I / O空间
- 10:32位存储空间
- 11:64位存储空间
- bbbbbbbb :PCI总线编号。PCI可以分层结构化。所以我们可能有PCI/PCI桥接器,它将定义子总线。
- ddddd :设备编号,通常与IDSEL信号连接相关联。
- fff :功能号码。用于多功能PCI设备。
- rrrrrrrr : 注册号; 用于配置周期。
出于PCI地址转换的目的,重要的字段是 p 和 ss 。phys.hi中p和ss的值决定了访问哪个PCI地址空间。因此,查看我们的范围属性,我们有三个区域:
- 一个32位可预取的存储区,从512 MB大小的PCI地址0x80000000开始,将映射到主机CPU上的地址0x80000000。
- 一个32位的非预取内存区域,从256 MB大小的PCI地址0xa0000000开始,将映射到主机CPU上的地址0xa0000000。
- 一个I/O区域,从16 MB大小的PCI地址0x00000000开始,将映射到主机CPU上的地址0xb0000000。
为了使wrench投入工作,phys.hi位域的存在意味着操作系统需要知道该节点代表PCI桥,以便它可以忽略不相关的字段以进行翻译。操作系统将在PCI总线节点中查找字符串“pci”,以确定是否需要屏蔽额外字段。
PCI DMA地址转换
上述范围定义了CPU如何查看PCI内存,并帮助CPU设置正确的内存窗口并将正确的参数写入各种PCI设备寄存器。这有时称为outbound memory。
地址转换的一个特例涉及PCI主机硬件如何看待系统的核心内存。当PCI主控制器充当主控制器,并独立访问系统的核心存储器时,会发生这种情况。由于这通常与CPU的视图不同(由于存储器线的连接方式),因此可能需要在初始化时将其编程到PCI主控制器中。这被视为一种DMA,因为PCI总线独立地执行直接存储器访问,因此映射被命名为dma-ranges。这种类型的内存映射有
时称为inbound memory,不是PCI设备树规范的一部分。
在某些情况下,ROM(BIOS)或类似设备将在启动时设置这些寄存器,但在其他情况下,PCI控制器完全未初始化,并且需要从设备树设置这些转换。然后,PCI主机驱动程序通常会解析dma-ranges属性并相应地在主机控制器中设置一些寄存器。
扩展上面的示例:
pci @ 0x10180000 { compatible =“arm,versatile-pci-hostbridge”,“pci”; reg = <0x10180000 0x1000>; interrupts = <8 0>; bus-ranges = <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 dma-ranges = <0x02000000 0 0x00000000 0x80000000 0 0x20000000 >;
};
此dma-ranges条目表示从PCI主机控制器的角度来看,PCI地址0x00000000处的512MB将出现在主核心存储器中的地址0x80000000处。如您所见,我们只是将ss地址类型设置为0x02,表明这是一些32位内存。
高级中断映射
现在我们来到最有趣的部分,PCI中断映射。PCI设备可以使用#INTA,#INTB,#INTC和#INTD触发中断。单功能设备有义务使用#INTA进行中断。如果多功能设备使用单个中断引脚,则必须使用#INTA,如果使用两个中断引脚,则必须使用#INB等等。由于这些规则,#INTA通常比#INTB,#INTC,#INTD具有更多的功能。为了分配中断#INTD到中断#INTA四个中断到四条IRQ中断线路上,每个PCI插槽或设备通常以旋转方式连接到中断控制器上的不同输入,以避免所有#INTA客户端连接到同一个输入中断线。此过程被称为混写(swizzling)中断。因此,设备树需要一种将每个PCI中断信号映射到中断控制器输入的方法。 #interrupt-cells , interrupt-map 和** interrupt-mapmask** 属性用于描述该中断的映射。
实际上,这里描述的中断映射不仅限于PCI总线,任何节点都可以指定复杂的中断映射,但PCI情况是目前最常见的。
pci @ 0x10180000 { compatible =“arm,versatile-pci-hostbridge”,“pci”; reg = <0x10180000 0x1000>; interrupts = <8 0>; bus-ranges = <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>;
#interrupt-cells = <1>; interrupt-map-mask = <0xf800 0 0 7>; interrupt-map = < 0xc000 0 0 1 &intc 9 3 // 1st slot 0xc000 0 0 2 &intc 10 3 0xc000 0 0 3 &intc 11 3 0xc000 0 0 4 &intc 12 3 0xc800 0 0 1 &intc 10 3 // 2nd slot 0xc800 0 0 2 &intc 11 3 0xc800 0 0 3 &intc 12 3 0xc800 0 0 4 &intc 9 3 >;
};
首先,你会注意到PCI中断号只使用一个cell,这与使用2个cells的系统中断控制器不同; 一个用于
irq中断号,一个用于中断属性标志。PCI仅需要一个cell用于中断,因为PCI中断被指定为始终是低电平敏感的。
在我们的示例板中,我们有2个PCI插槽,分别有4个中断线,因此我们必须将8个中断线映射到中断控制器。这是使用interrupt-map属性完成的。中断映射的确切过程在描述。
由于中断号(#INTA等)不足以区分单个PCI总线上的多个PCI设备,因此我们还必须表示哪个PCI设备触发了中断线。幸运的是,每个PCI设备都有一个我们可以使用的唯一设备号。为了区分几个PCI设备的中断,我们需要一个由PCI设备号和PCI中断号组成的元组。更一般地说,我们构造一个单元中断说明符,它有四个单元格:
- 三个#address-cells由phys.hi,phys.mid,phys.low和
- 一个#interrupt-cell(#INTA,#INTB,#INTC,#INTD)。
因为我们只需要PCI地址的设备号部分,所以interrupt-map-mask属性起作用。interrupt-mapmask也是一个像元素中断说明符一样的4元组。掩码中的1表示应考虑单元中断说明符的哪一部分。在我们的例子中,我们可以看到只需要phys.hi的设备号部分,我们需要3位来区分四条中断线(计数PCI中断线从1开始,而不是0!)。
现在我们可以构造interrupt-map属性。此属性是一个表,该表中的每个条目都包含一个子(PCI总线)单元中断说明符,一个父句柄(负责提供中断的中断控制器)和一个父单元中断说明符。因此,在第一行中,我们可以读到PCI中断#INTA映射到IRQ9,我们的中断控制器是低电平的。
目前唯一缺少的部分是PCI总线单元中断说明符中的奇怪数字。单元中断说明符的重要部分是来自phys.hi位字段的设备编号。设备编号是特定于板的,它取决于每个PCI主控制器如何激活每个设备上的IDSEL引脚。在该示例中,PCI插槽1被分配设备ID 24(0x18),并且PCI插槽2被分配设备ID25(0x19)。每个时隙的phys.hi值是通过将器件编号向上移位11位到位域的ddddd部分来确定的,如下所示:
- 插槽1的phys.hi是0xC000,并且
- 插槽2的phys.hi是0xC800。
将所有内容放在一起显示中断映射属性:
- 插槽1的#INTA是IRQ9,在主中断控制器上是低电平敏感的
- 插槽1的#INTB是IRQ10,在主中断控制器上是低电平敏感的
- 插槽1的#INTC是IRQ11,在主中断控制器上是低电平敏感的
- 插槽1的#INTD是IRQ12,在主中断控制器上是低电平敏感的
和
- 插槽2的#INTA是IRQ10,在主中断控制器上是低电平敏感的
- 插槽2的#INTB是IRQ11,在主中断控制器上是低电平敏感的
- 插槽2的#INTC是IRQ12,在主中断控制器上是低电平敏感的
- 插槽2的#INTD是IRQ9,在主中断控制器上是低电平敏感的
该** interrupts = <8 0>**; 属性描述了HOST/PCI桥控制器本身可能触发的中断。不要将这些中断与PCI设备可能触发的中断混淆(使用INTA,INTB,…)。
最后要注意的一件事。与中断父属性一样,节点上存在中断映射属性将更改所有子节点和孙节点的默认中断控制器。在此PCI示例中,这意味着PCI主桥成为默认的中断控制器。如果通过PCI总线连接的设备与另一个中断控制器直接连接,则还需要指定自己的中断父属性。