参考资料:《Linux设备驱动开发详解》
这我还有是有点惊讶
设备树竟然还可以保存中断信息。对于中断与硬件的关系,硬件怎么去触发中断,实现中断。有机会看看研究一下,中断。回到正题。
对于中断控制器而言,它提供如下属性:**interrupt-controller–这个属性为空,**中断控制器应该加上此属性表明自己的身份;
#interrupt-cells–与#address-cells和#size-cells相似,它表明连接此中断控制器的设备的中断属性的cell大小。
在整个设备树中,与中断相关的属性还包括:
interrupt-parent–设备节点通过它来指定它所依附的中断控制器的phandle,当节点没有指定interrupt-parent时,则从父级节点继承。对于本例(代码清单18.2)而言,根节点指定了interrupt-parent=<&intc>;,其对应于intc:interrupt-controller@10140000,而根节点的子节点并未指定interrupt-parent,因此它们都继承了intc,即位于0x10140000的中断控制器中。
interrupts–用到了中断的设备节点,通过它指定中断号、触发方法等,这个属性具体含有多少个cell,由它依附的中断控制器节点的#interrupt-cells属性决定。
而每个cell具体又是什么含义,一般由驱动的实现决定,而且也会在设备树的绑定文档中说明。譬如,对于ARM GIC中断控制器而言,#interrupt-cells为3,3个cell的具体含义在Documentation/devicetree/bindings/arm/gic.txt中就有如下文字说明:
The 1st cell is the interrupt type; 0 for SPI interrupts, 1 for PPI
interrupts.
The 2nd cell contains the interrupt number for the interrupt type.
SPI interrupts are in the range [0-987]. PPI interrupts are in the
range [0-15].
The 3rd cell is the flags, encoded as follows:
bits[3:0] trigger type and level flags.
1 = low-to-high edge triggered
2 = high-to-low edge triggered
4 = active high level-sensitive
8 = active low level-sensitive
bits[15:8] PPI interrupt cpu mask. Each bit corresponds to each of
the 8 possible cpus attached to the GIC. A bit set to '1' indicated
the interrupt is wired to that CPU. Only valid for PPI interrupts.
另外,值得注意的是,一个设备还可能用到多个中断号。对于ARM GIC而言,若某设备使用了SPI的168号、169号两个中断,而且都是高电平触发,则该设备节点的中断属性可定义为interrupts=<01684>,<01694>;。
对于平台设备而言,简单的通过如下API就可以指定想取哪一个中断,其中的参数num就是中断的index。
int platform_get_irq(struct platform_device *dev, unsigned int num);
当然在.dts文件中可以对中断进行命名,而后在驱动中通过platform_get_irq_byname()来获取对应的中断号。
譬如代码清单18.14演示了在drivers/dma/fsl-edma.c中通过platform_get_irq_byname()获取IRQ,以及arch/arm/boot/dts/vf610.dtsi与fsl-edma驱动对应节点的中断描述。
1 static int
2 fsl_edma_irq_init(struct platform_device *pdev,struct fsl_edma_engine *fsl_edma)
3 {
4 fsl_edma->txirq = platform_get_irq_byname(pdev, "edma-tx");
5 fsl_edma->errirq = platform_get_irq_byname(pdev, "edma-err");
6 }
7
8 edma0: dma-controller@40018000 {
9 #dma-cells = <2>;
10 compatible = "fsl,vf610-edma";
11 reg = <0x40018000 0x2000>,
12 <0x40024000 0x1000>,
13 <0x40025000 0x1000>;
14 interrupts = <0 8 IRQ_TYPE_LEVEL_HIGH>,
15 <0 9 IRQ_TYPE_LEVEL_HIGH>;
16 interrupt-names = "edma-tx", "edma-err";
17 dma-channels = <32>;
18 clock-names = "dmamux0", "dmamux1";
19 clocks = <&clks VF610_CLK_DMAMUX0>,
20 <&clks VF610_CLK_DMAMUX1>;
21 };
第4行、第5行的platform_get_irq_byname()的第2个参数与.dts中的interrupt-names是一致的。