设备树知识小全(八):中断连接

参考资料:《Linux设备驱动开发详解》

1、中断连接

这我还有是有点惊讶

设备树竟然还可以保存中断信息。对于中断与硬件的关系,硬件怎么去触发中断,实现中断。有机会看看研究一下,中断。回到正题。

对于中断控制器而言,它提供如下属性:**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是一致的。

你可能感兴趣的:(kernel,Linux,驱动开发,设备树)