在设备树中,节点的中断输出单元格大小为 1,但其中断父节点似乎有#interrupt-cells = 3。为什么?

In device tree, a node's interrupts output cell size is 1 but its interrupt-parent seems to have #interrupt-cells = 3. Why?

我正在通过修改现有文件来制作一个 dts 文件,但通过挖掘绑定文档仍然很难理解设备树语法和含义。这是另一个我无法理解的。请帮帮我..

在linux-5.15源代码中,我在arch/arm64/boot/dts/arm/fvp-base-revc.dts(显示部分)中看到,

#include "rtsm_ve-motherboard.dtsi"
#include "rtsm_ve-motherboard-rs2.dtsi"

/ {
    model = "FVP Base RevC";
    compatible = "arm,fvp-base-revc", "arm,vexpress";
    interrupt-parent = <&gic>;                              <== see this
    #address-cells = <2>;
    #size-cells = <2>;

    ...

    gic: interrupt-controller@2f000000 {
    compatible = "arm,gic-v3";
    #interrupt-cells = <3>;                                 <=== see this
    #address-cells = <2>;
    #size-cells = <2>;
    ranges;
    interrupt-controller;
    ....
    };

timer {
    compatible = "arm,armv8-timer";
    interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,             <== see these lines (3 values per cell)
             <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
             <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
             <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
};

所以因为 gic 有 #incterrupt-cells = <3>,(对于中断类型、编号和标志),生成 4 个中断的 timer 节点每个中断单元有 3 个值。但是在之前包含的文件 rtsm_ve-motherboard.dtsi 中,我看到了这一行。

        v2m_serial0: serial@90000 {
            compatible = "arm,pl011", "arm,primecell";
            reg = <0x090000 0x1000>;
            interrupts = <5>;                                  <== see this, (1 value per cell, why?)
            clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
            clock-names = "uartclk", "apb_pclk";
        };

        v2m_serial1: serial@a0000 {
            compatible = "arm,pl011", "arm,primecell";
            reg = <0x0a0000 0x1000>;
            interrupts = <6>;                                 <== see this, (1 value per cell, why?)
            clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
            clock-names = "uartclk", "apb_pclk";
        };

为什么这里的中断值只有1个单元格? (interrupts = <6>) 我在绑定文档或现有的 dts 文件中找不到任何指定 #interrupt-cells = 1 的中断控制器。 为什么v2m_serial0节点只有一个值interrupts值?

v2m_serial0: serial@90000 的路径是:

/bus@8000000/motherboard-bus@8000000/iofpga-bus@300000000/serial@90000

向根移动,具有 #interrupt-cells 属性 的第一个节点是 bus@8000000bus@8000000 节点部分定义在“rtsm_ve-motherboard.dtsi”文件中:

    bus@8000000 {
        compatible = "simple-bus";
        #address-cells = <2>;
        #size-cells = <1>;
        ranges = <0 0x8000000 0 0x8000000 0x18000000>;

        motherboard-bus@8000000 {

节点在“rtsm_ve-motherboard-rs2.dtsi”中定义了额外的material,现在不重要,在“fvp-base-revc.dts" 文件,其中包含 #interrupt-cells 属性:

    bus@8000000 {
        #interrupt-cells = <1>;
        interrupt-map-mask = <0 0 63>;
        interrupt-map = <0 0  0 &gic 0 0 GIC_SPI  0 IRQ_TYPE_LEVEL_HIGH>,
                <0 0  1 &gic 0 0 GIC_SPI  1 IRQ_TYPE_LEVEL_HIGH>,
                <0 0  2 &gic 0 0 GIC_SPI  2 IRQ_TYPE_LEVEL_HIGH>,
                <0 0  3 &gic 0 0 GIC_SPI  3 IRQ_TYPE_LEVEL_HIGH>,
                <0 0  4 &gic 0 0 GIC_SPI  4 IRQ_TYPE_LEVEL_HIGH>,
                <0 0  5 &gic 0 0 GIC_SPI  5 IRQ_TYPE_LEVEL_HIGH>,
                <0 0  6 &gic 0 0 GIC_SPI  6 IRQ_TYPE_LEVEL_HIGH>,

                <0 0 43 &gic 0 0 GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
                <0 0 44 &gic 0 0 GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
    };

#interrupt-cells 属性 的值为 1,这就是为什么子节点中的 interrupts 属性每个中断有一个单元格。

interrupt-map 属性 正在将单单元中断值映射到 &gic 中断控制器中的中断。上面的每个映射元素由 9 个单元格组成,包括:

  • 设备的 2 个地址单元格 (#address-cells = <2>)
  • 设备的 1 个中断单元 (#interrupt-cells = <1>)
  • 1 个包含上游中断控制器 phandle 的单元格
  • 上游中断控制器的 2 个地址单元 (#address-cells = <2>)
  • 3 个用于上游中断控制器的中断单元 (#interrupt-cells = <3>)

interrupt-map-mask属性由3个单元格组成,包括:

  • 2 个地址掩码单元匹配设备 reg 属性 (#address-cells = <2>)
  • 1 个中断屏蔽单元匹配设备 interrupt 属性 (#interrupt-cells = <1>)

v2m_serial0: serial@90000 节点具有以下 reginterrupts 属性:

                    reg = <0x090000 0x1000>;
                    interrupts = <5>;

地址和中断单元的组合值是 <0x090000 0x1000 5>。当ANDinterrupt-map-mask属性值<0 0 63>运算时,结果为<0 0 5>,匹配中断映射元素<0 0 5 &gic 0 0 GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>。因此,设备的 interrupts 属性 值映射到 &gic 中断控制器的 <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH> 中断值。

在“drivers/of/irq.c”中由of_irq_parse_raw()完成中断映射解析匹配。