Linux Device Tree in my eyes (four interruptions ),
4. Interruption
Interruptions generally include the generation of devices and the handling of devices. The Interrupt Controller is responsible for handling interruptions. Each interrupt has a corresponding interrupt number and trigger conditions. The device may have multiple interrupt sources. Sometimes multiple interrupt sources correspond to one interrupt in the interrupt controller. In this case, the interrupt source of the device is called the corresponding interrupt sub-interrupt in the interrupt controller. In general, the number of devices that are interrupted is more than that of the interrupt controller. One Interrupt Controller processes the number of devices that are interrupted by multiple interruptions. This multi-to-one relationship is also similar to a tree structure, therefore, in the Device Tree, the interrupt is also described as a tree called the interrupt tree. In the following statement, we add the word "interrupt" to the front of the parent node and the child node to indicate the interrupt tree, it is to prevent confusion with the parent and child nodes of the Device Tree (although in most cases, the parent-child relationship of the device tree is the parent-child relationship of the interrupt tree, but because there are special cases, so we should emphasize that the parent-child relationship is interrupted ).
The interrupts attribute is used to describe the interrupt source (interrupt specifier). Because different hardware descriptions require different data volumes, the type of the interrupts attribute is also <prop-encoded-array>. The # interrupt-cells attribute is introduced to indicate that an interrupt is represented by several u32 characters. # The type of the interrupt-cells attribute is u32, if two u32 pairs are required for one interrupt source (one indicates the interrupt number and the other indicates the interrupt type), set # interrupt-cells to 2. In some cases, the parent node of the device tree is not the interrupted parent node (mainly the interrupt controller is not the parent node). Therefore, the interrupt-parent attribute is introduced, the type of this attribute is <phandle>, which is used to reference the parent node that is interrupted (as we have said before, the label of the parent node is generally used, there is a reason to interrupt the parent node rather than the Controller ). If the parent node of the Device Tree interrupts the parent node, you do not need to set the interrupt-parent attribute. The interrupts attribute and interrupt-parent attribute are the attributes of the device node that is interrupted, but # The interrupt-cells attribute is not, # The interrupt-cells attribute is the attributes of the interrupt controller node and interrupt nexus node, both types of nodes may interrupt the parent node.
The interrupt controller node uses the interrupt-controller attribute to indicate that it is an interrupt controller. The type of this attribute is null and no value is set. If this node exists, it indicates that the node is an interrupt controller. In addition to this attribute, the interrupt controller node also has the # interrupt-cells attribute, used to indicate the interrupt domain managed by the interrupt controller (the interrupt subnode interrupt nexus node of the interrupt controller has a separate interrupt domain) several u32 are used to represent an interrupt source (interrupt specifier ). The interrupt controller node includes two attributes about interrupt: interrupt-controller and # interrupt-cells. The # address-cells attribute of the interrupt controller is related to the interrupt ing. However, this attribute is not designed for the interrupt, And the interrupt ing only uses this attribute.
In the front side, one interrupt in the interrupt controller may correspond to multiple interrupt sources in the Interrupt Device. What is the description of this relationship? We also said that the # interrupt-celll attribute is not only the attribute of the interrupt controller node, but also the attribute of the interrupt nexus node. This interrupt nexus node describes the interrupt ing relationship, this node uses the interrupt-map and interrupt-map-mask attributes to describe the interrupt ing relationship. The interrupt-map attribute is of the <prop-encoded-array> type. Each element represents an interrupt ing (note that it is an "interrupt ing ", is not "an interrupt" ing relationship), including: interrupt sub-device address, interrupt sub-device interrupt source (interrupt specifier), interrupt parent device, interrupt parent device address, interrupt specifier. The address of the interrupt sub-device consists of several u32 nodes, which are determined by the address-cells attribute of the bus where the interrupt sub-device is located (not the parent device, there is a reason why the device address is interrupted instead of the device's phandle, because the device will be interrupted with the interrupt-parrent attribute pointing to the parent node, therefore, it is OK to interrupt the sub-device. Because the sub-device address is interrupted, you can use the interrupt-map-mask attribute to map multiple to one. The interrupt sub-device interrupt source (interrupt specifier) consists of several u32, which is determined by # interrupt-cell under the interrupt nexus node. The interrupt parent device is a <phandle> attribute pointing to the interrupt parent device. Generally, it is an interrupt controller. However, according to the logic of the interrupt tree, it may also be a higher level of interrupt nexus node. The address of the parent device to be interrupted consists of several u32 nodes, which are determined by the # address-cells attribute under the parent device node to be interrupted (note, it is not the # address-cells attribute that interrupts the bus where the parent device is located ). The interrupt source (interrupt specifier) consists of several u32, which is determined by the # interrupt-cells attribute of the parent device that is interrupted.
Remember that the front side said that the interrupt source of the interrupt device and the interrupt source of the interrupt controller may be multiple-to-one. If each sub-interrupt is represented by a line in interrupt-map, therefore, the interrupt-map attribute will be very large. The interrupt-map-mask attribute is introduced to interrupt the sharing ing relationship among multiple sub-accounts. The attribute type is also <prop-enaco-array>, the bit mask that contains the address of the interrupt sub-device and the source of the interrupt sub-device. Given a sub-interrupt source, first perform operations with interrupt-map-mask, then, use the interrupt-map attribute to find the source of the parent device interruption. This is why we say that the line of the interrupt-map attribute is an "interrupt ing relationship", rather than a "interrupt" ing relationship.
Let's review it. The bottom layer of the entire interrupt tree is the interrupt generation device (or possibly from the interrupt nexus node). The interrupt generation device uses the interrupts attribute to describe the interrupt that it can cause. Because the parent device of the interrupt device may be different from the parent device of the Device Tree, use the interrupt-parent attribute to point to the parent device of the interrupt device. The parent device may be interrupted by the interrupt controller (if the interrupt of the device is one-to-one, or the lowest layer is the interrupt nexus node ), it may also be an interrupt nexus node (if the device is interrupted at the bottom layer and needs to be mapped ). The interrupt nexus node and all its direct sub-nodes constitute an interrupt domain. The meaning of the interrupt source under the interrupt domain is determined by the # interrupt-cells attribute, the interrupt-map and interrupt-map-mask attributes determine how to locate the parent device interruption source by the interruption sub-device interruption source. The parent node of interrupt nexus may be an interrupt nexus parent node, or an interrupt controller. When the last interrupt controller is found up and the interrupt controller has no longer interrupted the parent device, the entire interrupt tree is traversed. The interrupt controller uses the interrupt-controller attribute to indicate that it is an interrupt controller, and uses the # interrupt-cells attribute to indicate that the interrupt domain managed by the interrupt controller uses several u32 to indicate an interrupt source. According to the characteristics of the interrupt tree, multiple interrupt trees may exist in a device tree.
The above is the rule of how interruptions are described in the Device Tree. It sounds complicated, but it is very easy to understand. To help us understand it, let's give a practical example. To highlight the interruption, we simplified it.
/{
Model = "Marvell Armada 375 family SoC ";
Compatible = "marvell, armada375 ";
Soc {
# Address-cells = <2>;
# Size-cells = <1>;
Interrupt-parent = <& gic>;
Internal-regs {
Compatible = "simple-bus ";
# Address-cells = <1>;
# Size-cells = <1>;
Timer @ c600 {
Compatible = "arm, cortex-a9-twd-timer ";
Reg = <0xc600 0x20>;
Interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE (2)>;
Clocks = <& coreclk 2>;
};
Gic: interrupt-controller @ d000 {
Compatible = "arm, cortex-a9-gic ";
# Interrupt-cells = <3>;
# Address-cells = <0>;
Interrupt-controller;
Reg = <0xd000 0x1000>,
<0xc100 0x100>;
};
}
Pcie-controller {
Compatible = "marvell, armada-370-pcie ";
# Address-cells = <3>;
# Size-cells = <2>;
Pcie @ 1, 0 {
# Address-cells = <3>;
# Size-cells = <2>;
# Interrupt-cells = <1>;
Interrupt-map-mask = <0 0 0>;
Interrupt-map = <0 0 0 & gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
};
};
}
First, we can see that the device node timer @ c600 defines the interrupts attribute, which indicates that the device can be interrupted, however, we cannot see several interruptions in this attribute. (If we have experience, we can guess that it is just an interruption. Now we confirm it according to the rules ). Because the node does not have the interrupt-parent attribute, the Device Tree's parent node, internal-regs, is considered to be the parent node that interrupts the device tree. There is still no interrupt-parent attribute under the internal-regs parent node, continue to find the parent node of the Device Tree and find the soc, which has the interrupt-parent attribute. The tag referenced by this attribute is gic, and the entire Device Tree is searched. The tag of interrupt-controller @ d000 is gic. The interrupt-controller attribute in the gic node indicates that it is an interrupt controller. The gic Node also has the attribute # interrupt-cells = <3>. It indicates that under the interrupt domain of the Controller, the interrupt source (interrupt specifier) is represented by three u32, let's look at the interrupts attribute under timer @ c600, which is indeed composed of three u32 (refer to the GIC specification. The first u32 indicates the interrupt type, and the second is the interrupt number, the third is the trigger condition of the interrupt ). This example shows that if the interrupt source and the interrupt source of the interrupt controller are one-to-one, interrupt nexus nodes and related attributes are not required to represent the interrupt ing.
Look at the pcie @ node, which has the # interrupt-cells attribute but does not have the interrupt-controller attribute. This indicates that it is an interrupt nexus node. The # interrupt-cells attribute of this node is 1, indicating that the interrupt source under the interrupt nexus node is represented by one u32. There are no subnodes under the pcie @ node, and no interrupt-parent attribute of the node points to the pcie @ node. Therefore, the interrupt generation device under the interrupt domain cannot be seen from the Device Tree, the possible cause is that the device software generated by these interruptions can be dynamically identified, so the Device Tree description is not required. Because the interrupt-map-mask attribute is composed of the address and the interrupt source (interrupt specifier) of the interrupt device, and the interrupt source is represented by one u32, it can be inferred that the device address generated by the interruption is composed of three u32. Note that the # address-cells attribute of pcie @ node is 3, indicating that the device address under the bus is represented by three u32 nodes, however, it does not mean that the device address that causes the device to be interrupted must be 3 u32, which cannot be a coincidence, however, we need to know that the IP address of the device generated by the interruption is determined by the bus where the device is located. The pcie bus is indeed 3, but other bus may have other cases. Now let's analyze the interrupt-map attribute. The first three digits are the IP address of the interrupt device, and the fourth digit is the source of the interrupt device. Because interrupt-map-mask is all 0, No matter what number is used and the calculation result is 0, the first four digits of the interrupt-map attribute are also 0, this indicates that all the interruptions mapped to the interrupted parent node under pcie @ 1 and 0 are interrupted. Next, it points to <phandle> of gic. Because the # address-cells attribute under the gic node is 0, you do not need to describe the address to interrupt the parent device, the three digits below indicate that the source of the parent device is interrupted. In one statement, all interrupts under pcie @ 29th are mapped to the gic, GIC_SPI type interrupt, and the trigger type is High Level Trigger. This example shows that the bottom of the interrupt tree can be an interrupt nexus node.
In the preceding example, the root of the interrupt tree is gic, and there are two children under gic. One is the interrupt Device timer @ c600, and the other is the interrupt nexus node pcie. The interrupt domain under the direct jurisdiction of gic uses three u32 to represent the interrupt source, and the timer @ c600 is under the interrupt domain. Pcie @ defines a new interrupt domain. Under the interrupt domain, the interrupt source is represented by one u32, pcie @ Use the interrupt-map and interrupt-map-mask attributes to map all the device interruptions to the interruptions under a gic.