中断树模型:在设备树中,存在逻辑中断树,该逻辑中断树表示平台硬件中的中断的层次结构和路由。虽然通常称为中断树,其实它的结构是有向无环图。
在设备树中,使用interrupt-parent
属性表示中断源与中断控制器的物理连线。代表中断产生设备的节点都包含interrupt-parent
属性,该值用于接收中断的设备。
中断域的概念:在中断初始化过程中,Linux内核会从特定整数区间中选取一个整数作为一个中断源
interrupt source
的编号,并且使每个中断源都有一个独一无二且不重复的编号。如果系统仅存有一个中断控制器,那么能简单地给每个引脚对应的中断源分配一个编号。不过,如前所述,在有些情况下系统可能配置了多个中断控制器,所以中断源的编号方式将会有点复杂。因此内核需要一种机制去管理硬件中断编号hwirq
与Linux中断编号irq
之间的映射,以便使多个中断控制器之间不会出现重复相同的irq
。正因如此,内核抽象出了中断域概念,由它实现处理中断号的分配和管理。
例如,定义了一个soc的设备树文件。
根据interrupt-parent属性可以整理出该设备树中的中断树,如下
从这个例子中大致可以了解interrupt-parent
属性的作用,就是明确的指出设备树中跟中断相关的各个设备的关系。
产生中断的设备属性
interrupts属性
值的类型:prop-encoded-array
描述:设备的interrupts
属性定义了设备产生的中断
例子:在开放的PIC兼容中断域中,中断说明符的常见定义由两个单元组成。第一个单元定义了中断数和中断等级。下面定义的中断说明符,中断数是0xA,中断等级为8。
interrupts = <0xA 8>;
interrupt-parent属性
值的类型:phandle
描述:由于节点在中断树中的层级和在设备树中的层级可能不匹配。所以设定了这个属性用来显式的指定中断源。
interrupts-extended属性
值的类型: phandle prop-encodeed-array
描述:该属性描述了该设备能够产生的中断。当存在多个中断控制器时,使用interrupts-extended
代替interrupts
描述中断。
例子:下面的代码,描述了两个中断输入分别接在两个不同的中断控制器上,pic是一个#interrupt-cells
属性为2的中断控制器,gic是一个#interrupt-cells
属性为1的中断控制器。
interrupts-extended = <&pic 0xA 8>, <&gic 0xda>;
中断控制器的属性
#interrupt-cells
属性
值的类型: <u32>
描述:该属性定义了一个中断说明符(中断域)所需要的单元数。
interrupt-controller属性
值的类型: 空值
描述:该属性将包含该属性的节点定义为中断控制器。
中断链接属性
每个中断链接节点都要拥有#interrupt-cells
属性。
interrupt-map属性
值的类型:prop-encode-array
该属性将一个中断域与一组父中断域桥接,并指定子域中的中断说明符如何映射到其各自的父域。
每一行有5项,格式如下:
child unit address
: 子节点的单元地址child interrupt specifier
: 子节点的中断说明符interrupt-parent
: 该值指向子节点将被映射到的中断父域parent unit address
: 中断父域的地址parent interrupt specifier
: 父域中的中断描述符interrupt-map-mask属性
值的类型:
prop-encoded-array
该属性指定了设备树中的链接节点#interrupt-cells属性
值的类型:
<u32>
该属性定义了一个中断说明符(中断域)所需要的单元数。中断映射的例子
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 */
>;
};
};
中断映射表的每一行都包含5个部分,第一行的组成如下:
child unit address
:0x8800 0 0
(pci的#address-cells
属性是3)child interrupt specifier
:1
(pci的#interrupt-cells
属性是1)interrupt parent
:&open-pic
parent unit address
:是空的(open-pic
的address-cells
为0)parent interrupt specifier
:2 1
(open-pic
的#interrupt-cells
属性是2)
在这个例子中,interrupt-map-mask
属性的值为<0xf800 0 0 7>
上面的设备树文件主要描述的就是一个具有两个pci
插槽的soc
,两个pci
直接连在soc
上,总线号为0x0
,pci
的设备号,一个是0x11
,另一个是0x12
。要从open-pic
找到function 0x3,IDSEL 0x12(slot2)
的父级中断域的说明符(子中断域说明符为2),需要执行以下步骤:
- 先得到设备A的子单元地址和中断说明符,步骤是这样的,总线号左移16位(0x0<<16),设备号左移11位(0x12<<11),函数号左移8位(0x3<<8),得到的结果`<0x9300 0 0 2>`
- 把上面中得到的结果与
interrupt-map-mask
进行与操作,得到结果<0x9000 0 0 2>
- 根据中断映射表得到父级中断说明符为
<4 1>