-1

I'm making a dts file by modifying an existing one and it's still hard to understand device tree syntax and meaning with digging the bindings documents. Here is another one I can't understand. Please help me..

In linux-5.15 source, I see in arch/arm64/boot/dts/arm/fvp-base-revc.dts (showing parts),

#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>;
};

So because gic has #incterrupt-cells = <3>, (for interrupt type, number and flag), the timer node generating 4 interrupts has 3 values for each interrupts cell. But in file rtsm_ve-motherboard.dtsi which is included earlier, I see this lines.

        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";
        };

Why does the interrupts value has only 1 cell here? (interrupts = <6>) I couldn't find any interrupt controller specifying #interrupt-cells = 1 in the binding documents or existing dts files. Why does v2m_serial0 node has only one value for interrupts value?

Chan Kim
  • 5,177
  • 12
  • 57
  • 112

1 Answers1

1

The path to v2m_serial0: serial@90000 is:

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

Going up to towards the root, the first node with an #interrupt-cells property is bus@8000000. The bus@8000000 node is partly defined in the "rtsm_ve-motherboard.dtsi" file:

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

        motherboard-bus@8000000 {

The node has additional material defined in the "rtsm_ve-motherboard-rs2.dtsi", which is not important right now, and in the "fvp-base-revc.dts" file, which contains the #interrupt-cells property:

    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>;
    };

The #interrupt-cells property has value 1, so that is why the interrupts properties in the child nodes have one cell per interrupt.

The interrupt-map property is mapping the one-cell interrupt values to interrupts in the &gic interrupt controller. Each mapping element above consists of 9 cells, comprising of:

  • 2 address cells for the device (#address-cells = <2>)
  • 1 interrupt cell for the device (#interrupt-cells = <1>)
  • 1 cell containing a phandle for the upstream interrupt controller
  • 2 address cells for the upstream interrupt controller (#address-cells = <2>)
  • 3 interrupt cells for the upstream interrupt controller (#interrupt-cells = <3>)

The interrupt-map-mask property consists of 3 cells, comprising:

  • 2 address mask cells to match against the device reg property (#address-cells = <2>)
  • 1 interrupt mask cell to match against the device interrupt property (#interrupt-cells = <1>)

The v2m_serial0: serial@90000 node has the following reg and interrupts properties:

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

The combined address and interrupts cell values are <0x090000 0x1000 5>. When AND-ed with the interrupt-map-mask property value <0 0 63>, the result is <0 0 5>, which matches the interrupt mapping element <0 0 5 &gic 0 0 GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>. Therefore, the device's interrupts property value is mapped to the <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH> interrupt value for the &gic interrupt controller.

The interrupt map parsing and matching is done by of_irq_parse_raw() in "drivers/of/irq.c".

Ian Abbott
  • 15,083
  • 19
  • 33
  • Thank you so much. I learned more about how to carefully look at the hierarchy and overlay information, and I wasn't aware of the interrupt-map yet. – Chan Kim Nov 06 '21 at 01:55