Loading Documentation/IRQ-domain.txt +71 −0 Original line number Diff line number Diff line Loading @@ -151,3 +151,74 @@ used and no descriptor gets allocated it is very important to make sure that the driver using the simple domain call irq_create_mapping() before any irq_find_mapping() since the latter will actually work for the static IRQ assignment case. ==== Hierarchy IRQ domain ==== On some architectures, there may be multiple interrupt controllers involved in delivering an interrupt from the device to the target CPU. Let's look at a typical interrupt delivering path on x86 platforms: Device --> IOAPIC -> Interrupt remapping Controller -> Local APIC -> CPU There are three interrupt controllers involved: 1) IOAPIC controller 2) Interrupt remapping controller 3) Local APIC controller To support such a hardware topology and make software architecture match hardware architecture, an irq_domain data structure is built for each interrupt controller and those irq_domains are organized into hierarchy. When building irq_domain hierarchy, the irq_domain near to the device is child and the irq_domain near to CPU is parent. So a hierarchy structure as below will be built for the example above. CPU Vector irq_domain (root irq_domain to manage CPU vectors) ^ | Interrupt Remapping irq_domain (manage irq_remapping entries) ^ | IOAPIC irq_domain (manage IOAPIC delivery entries/pins) There are four major interfaces to use hierarchy irq_domain: 1) irq_domain_alloc_irqs(): allocate IRQ descriptors and interrupt controller related resources to deliver these interrupts. 2) irq_domain_free_irqs(): free IRQ descriptors and interrupt controller related resources associated with these interrupts. 3) irq_domain_activate_irq(): activate interrupt controller hardware to deliver the interrupt. 3) irq_domain_deactivate_irq(): deactivate interrupt controller hardware to stop delivering the interrupt. Following changes are needed to support hierarchy irq_domain. 1) a new field 'parent' is added to struct irq_domain; it's used to maintain irq_domain hierarchy information. 2) a new field 'parent_data' is added to struct irq_data; it's used to build hierarchy irq_data to match hierarchy irq_domains. The irq_data is used to store irq_domain pointer and hardware irq number. 3) new callbacks are added to struct irq_domain_ops to support hierarchy irq_domain operations. With support of hierarchy irq_domain and hierarchy irq_data ready, an irq_domain structure is built for each interrupt controller, and an irq_data structure is allocated for each irq_domain associated with an IRQ. Now we could go one step further to support stacked(hierarchy) irq_chip. That is, an irq_chip is associated with each irq_data along the hierarchy. A child irq_chip may implement a required action by itself or by cooperating with its parent irq_chip. With stacked irq_chip, interrupt controller driver only needs to deal with the hardware managed by itself and may ask for services from its parent irq_chip when needed. So we could achieve a much cleaner software architecture. For an interrupt controller driver to support hierarchy irq_domain, it needs to: 1) Implement irq_domain_ops.alloc and irq_domain_ops.free 2) Optionally implement irq_domain_ops.activate and irq_domain_ops.deactivate. 3) Optionally implement an irq_chip to manage the interrupt controller hardware. 4) No need to implement irq_domain_ops.map and irq_domain_ops.unmap, they are unused with hierarchy irq_domain. Hierarchy irq_domain may also be used to support other architectures, such as ARM, ARM64 etc. Documentation/devicetree/bindings/arm/gic-v3.txt +39 −0 Original line number Diff line number Diff line Loading @@ -49,11 +49,29 @@ Optional occupied by the redistributors. Required if more than one such region is present. Sub-nodes: GICv3 has one or more Interrupt Translation Services (ITS) that are used to route Message Signalled Interrupts (MSI) to the CPUs. These nodes must have the following properties: - compatible : Should at least contain "arm,gic-v3-its". - msi-controller : Boolean property. Identifies the node as an MSI controller - reg: Specifies the base physical address and size of the ITS registers. The main GIC node must contain the appropriate #address-cells, #size-cells and ranges properties for the reg property of all ITS nodes. Examples: gic: interrupt-controller@2cf00000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; #address-cells = <2>; #size-cells = <2>; ranges; interrupt-controller; reg = <0x0 0x2f000000 0 0x10000>, // GICD <0x0 0x2f100000 0 0x200000>, // GICR Loading @@ -61,11 +79,20 @@ Examples: <0x0 0x2c010000 0 0x2000>, // GICH <0x0 0x2c020000 0 0x2000>; // GICV interrupts = <1 9 4>; gic-its@2c200000 { compatible = "arm,gic-v3-its"; msi-controller; reg = <0x0 0x2c200000 0 0x200000>; }; }; gic: interrupt-controller@2c010000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; #address-cells = <2>; #size-cells = <2>; ranges; interrupt-controller; redistributor-stride = <0x0 0x40000>; // 256kB stride #redistributor-regions = <2>; Loading @@ -76,4 +103,16 @@ Examples: <0x0 0x2c060000 0 0x2000>, // GICH <0x0 0x2c080000 0 0x2000>; // GICV interrupts = <1 9 4>; gic-its@2c200000 { compatible = "arm,gic-v3-its"; msi-controller; reg = <0x0 0x2c200000 0 0x200000>; }; gic-its@2c400000 { compatible = "arm,gic-v3-its"; msi-controller; reg = <0x0 0x2c400000 0 0x200000>; }; }; arch/arm/boot/dts/qcom/msm8996.dtsi +144 −134 Original line number Diff line number Diff line Loading @@ -250,13 +250,23 @@ intc: interrupt-controller@09bc0000 { compatible = "arm,gic-v3"; reg = <0x9bc0000 0x10000>, /* GICD */ <0x9c00000 0x100000>; /* GICR * 4 */ #interrupt-cells = <3>; #address-cells = <1>; #size-cells = <1>; ranges; interrupt-controller; #redistributor-regions = <1>; redistributor-stride = <0x0 0x40000>; reg = <0x09bc0000 0x10000>, /* GICD */ <0x09c00000 0x100000>; /* GICR * 4 */ interrupts = <1 9 4>; gic-its@09BE0000 { compatible = "arm,gic-v3-its"; msi-contoller; reg = <0x9be0000 0x20000>; }; }; timer { Loading Loading @@ -1222,50 +1232,50 @@ 39 40 41 42 43>; #interrupt-cells = <1>; interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 405 0 0x0 0x0 0x0 1 &intc 0 244 0 0x0 0x0 0x0 2 &intc 0 245 0 0x0 0x0 0x0 3 &intc 0 247 0 0x0 0x0 0x0 4 &intc 0 248 0 0x0 0x0 0x0 5 &intc 0 249 0 0x0 0x0 0x0 6 &intc 0 250 0 0x0 0x0 0x0 7 &intc 0 251 0 0x0 0x0 0x0 8 &intc 0 252 0 0x0 0x0 0x0 9 &intc 0 253 0 0x0 0x0 0x0 10 &intc 0 254 0 0x0 0x0 0x0 11 &intc 0 255 0 0x0 0x0 0x0 12 &intc 0 512 0 0x0 0x0 0x0 13 &intc 0 513 0 0x0 0x0 0x0 14 &intc 0 514 0 0x0 0x0 0x0 15 &intc 0 515 0 0x0 0x0 0x0 16 &intc 0 516 0 0x0 0x0 0x0 17 &intc 0 517 0 0x0 0x0 0x0 18 &intc 0 518 0 0x0 0x0 0x0 19 &intc 0 519 0 0x0 0x0 0x0 20 &intc 0 520 0 0x0 0x0 0x0 21 &intc 0 521 0 0x0 0x0 0x0 22 &intc 0 522 0 0x0 0x0 0x0 23 &intc 0 523 0 0x0 0x0 0x0 24 &intc 0 524 0 0x0 0x0 0x0 25 &intc 0 525 0 0x0 0x0 0x0 26 &intc 0 526 0 0x0 0x0 0x0 27 &intc 0 527 0 0x0 0x0 0x0 28 &intc 0 528 0 0x0 0x0 0x0 29 &intc 0 529 0 0x0 0x0 0x0 30 &intc 0 530 0 0x0 0x0 0x0 31 &intc 0 531 0 0x0 0x0 0x0 32 &intc 0 532 0 0x0 0x0 0x0 33 &intc 0 533 0 0x0 0x0 0x0 34 &intc 0 534 0 0x0 0x0 0x0 35 &intc 0 535 0 0x0 0x0 0x0 36 &intc 0 536 0 0x0 0x0 0x0 37 &intc 0 537 0 0x0 0x0 0x0 38 &intc 0 538 0 0x0 0x0 0x0 39 &intc 0 539 0 0x0 0x0 0x0 40 &intc 0 540 0 0x0 0x0 0x0 41 &intc 0 541 0 0x0 0x0 0x0 42 &intc 0 542 0 0x0 0x0 0x0 43 &intc 0 543 0>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 405 0 0x0 0x0 0x0 1 &intc 0 0 244 0 0x0 0x0 0x0 2 &intc 0 0 245 0 0x0 0x0 0x0 3 &intc 0 0 247 0 0x0 0x0 0x0 4 &intc 0 0 248 0 0x0 0x0 0x0 5 &intc 0 0 249 0 0x0 0x0 0x0 6 &intc 0 0 250 0 0x0 0x0 0x0 7 &intc 0 0 251 0 0x0 0x0 0x0 8 &intc 0 0 252 0 0x0 0x0 0x0 9 &intc 0 0 253 0 0x0 0x0 0x0 10 &intc 0 0 254 0 0x0 0x0 0x0 11 &intc 0 0 255 0 0x0 0x0 0x0 12 &intc 0 0 512 0 0x0 0x0 0x0 13 &intc 0 0 513 0 0x0 0x0 0x0 14 &intc 0 0 514 0 0x0 0x0 0x0 15 &intc 0 0 515 0 0x0 0x0 0x0 16 &intc 0 0 516 0 0x0 0x0 0x0 17 &intc 0 0 517 0 0x0 0x0 0x0 18 &intc 0 0 518 0 0x0 0x0 0x0 19 &intc 0 0 519 0 0x0 0x0 0x0 20 &intc 0 0 520 0 0x0 0x0 0x0 21 &intc 0 0 521 0 0x0 0x0 0x0 22 &intc 0 0 522 0 0x0 0x0 0x0 23 &intc 0 0 523 0 0x0 0x0 0x0 24 &intc 0 0 524 0 0x0 0x0 0x0 25 &intc 0 0 525 0 0x0 0x0 0x0 26 &intc 0 0 526 0 0x0 0x0 0x0 27 &intc 0 0 527 0 0x0 0x0 0x0 28 &intc 0 0 528 0 0x0 0x0 0x0 29 &intc 0 0 529 0 0x0 0x0 0x0 30 &intc 0 0 530 0 0x0 0x0 0x0 31 &intc 0 0 531 0 0x0 0x0 0x0 32 &intc 0 0 532 0 0x0 0x0 0x0 33 &intc 0 0 533 0 0x0 0x0 0x0 34 &intc 0 0 534 0 0x0 0x0 0x0 35 &intc 0 0 535 0 0x0 0x0 0x0 36 &intc 0 0 536 0 0x0 0x0 0x0 37 &intc 0 0 537 0 0x0 0x0 0x0 38 &intc 0 0 538 0 0x0 0x0 0x0 39 &intc 0 0 539 0 0x0 0x0 0x0 40 &intc 0 0 540 0 0x0 0x0 0x0 41 &intc 0 0 541 0 0x0 0x0 0x0 42 &intc 0 0 542 0 0x0 0x0 0x0 43 &intc 0 0 543 0>; interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d", "int_pls_pme", "int_pme_legacy", "int_pls_err", Loading Loading @@ -1376,50 +1386,50 @@ 39 40 41 42 43>; #interrupt-cells = <1>; interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 413 0 0x0 0x0 0x0 1 &intc 0 272 0 0x0 0x0 0x0 2 &intc 0 273 0 0x0 0x0 0x0 3 &intc 0 274 0 0x0 0x0 0x0 4 &intc 0 275 0 0x0 0x0 0x0 5 &intc 0 276 0 0x0 0x0 0x0 6 &intc 0 277 0 0x0 0x0 0x0 7 &intc 0 278 0 0x0 0x0 0x0 8 &intc 0 279 0 0x0 0x0 0x0 9 &intc 0 280 0 0x0 0x0 0x0 10 &intc 0 281 0 0x0 0x0 0x0 11 &intc 0 282 0 0x0 0x0 0x0 12 &intc 0 544 0 0x0 0x0 0x0 13 &intc 0 545 0 0x0 0x0 0x0 14 &intc 0 546 0 0x0 0x0 0x0 15 &intc 0 547 0 0x0 0x0 0x0 16 &intc 0 548 0 0x0 0x0 0x0 17 &intc 0 549 0 0x0 0x0 0x0 18 &intc 0 550 0 0x0 0x0 0x0 19 &intc 0 551 0 0x0 0x0 0x0 20 &intc 0 552 0 0x0 0x0 0x0 21 &intc 0 553 0 0x0 0x0 0x0 22 &intc 0 554 0 0x0 0x0 0x0 23 &intc 0 555 0 0x0 0x0 0x0 24 &intc 0 556 0 0x0 0x0 0x0 25 &intc 0 557 0 0x0 0x0 0x0 26 &intc 0 558 0 0x0 0x0 0x0 27 &intc 0 559 0 0x0 0x0 0x0 28 &intc 0 560 0 0x0 0x0 0x0 29 &intc 0 561 0 0x0 0x0 0x0 30 &intc 0 562 0 0x0 0x0 0x0 31 &intc 0 563 0 0x0 0x0 0x0 32 &intc 0 564 0 0x0 0x0 0x0 33 &intc 0 565 0 0x0 0x0 0x0 34 &intc 0 566 0 0x0 0x0 0x0 35 &intc 0 567 0 0x0 0x0 0x0 36 &intc 0 568 0 0x0 0x0 0x0 37 &intc 0 569 0 0x0 0x0 0x0 38 &intc 0 570 0 0x0 0x0 0x0 39 &intc 0 571 0 0x0 0x0 0x0 40 &intc 0 572 0 0x0 0x0 0x0 41 &intc 0 573 0 0x0 0x0 0x0 42 &intc 0 574 0 0x0 0x0 0x0 43 &intc 0 575 0>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 413 0 0x0 0x0 0x0 1 &intc 0 0 272 0 0x0 0x0 0x0 2 &intc 0 0 273 0 0x0 0x0 0x0 3 &intc 0 0 274 0 0x0 0x0 0x0 4 &intc 0 0 275 0 0x0 0x0 0x0 5 &intc 0 0 276 0 0x0 0x0 0x0 6 &intc 0 0 277 0 0x0 0x0 0x0 7 &intc 0 0 278 0 0x0 0x0 0x0 8 &intc 0 0 279 0 0x0 0x0 0x0 9 &intc 0 0 280 0 0x0 0x0 0x0 10 &intc 0 0 281 0 0x0 0x0 0x0 11 &intc 0 0 282 0 0x0 0x0 0x0 12 &intc 0 0 544 0 0x0 0x0 0x0 13 &intc 0 0 545 0 0x0 0x0 0x0 14 &intc 0 0 546 0 0x0 0x0 0x0 15 &intc 0 0 547 0 0x0 0x0 0x0 16 &intc 0 0 548 0 0x0 0x0 0x0 17 &intc 0 0 549 0 0x0 0x0 0x0 18 &intc 0 0 550 0 0x0 0x0 0x0 19 &intc 0 0 551 0 0x0 0x0 0x0 20 &intc 0 0 552 0 0x0 0x0 0x0 21 &intc 0 0 553 0 0x0 0x0 0x0 22 &intc 0 0 554 0 0x0 0x0 0x0 23 &intc 0 0 555 0 0x0 0x0 0x0 24 &intc 0 0 556 0 0x0 0x0 0x0 25 &intc 0 0 557 0 0x0 0x0 0x0 26 &intc 0 0 558 0 0x0 0x0 0x0 27 &intc 0 0 559 0 0x0 0x0 0x0 28 &intc 0 0 560 0 0x0 0x0 0x0 29 &intc 0 0 561 0 0x0 0x0 0x0 30 &intc 0 0 562 0 0x0 0x0 0x0 31 &intc 0 0 563 0 0x0 0x0 0x0 32 &intc 0 0 564 0 0x0 0x0 0x0 33 &intc 0 0 565 0 0x0 0x0 0x0 34 &intc 0 0 566 0 0x0 0x0 0x0 35 &intc 0 0 567 0 0x0 0x0 0x0 36 &intc 0 0 568 0 0x0 0x0 0x0 37 &intc 0 0 569 0 0x0 0x0 0x0 38 &intc 0 0 570 0 0x0 0x0 0x0 39 &intc 0 0 571 0 0x0 0x0 0x0 40 &intc 0 0 572 0 0x0 0x0 0x0 41 &intc 0 0 573 0 0x0 0x0 0x0 42 &intc 0 0 574 0 0x0 0x0 0x0 43 &intc 0 0 575 0>; interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d", "int_pls_pme", "int_pme_legacy", "int_pls_err", Loading Loading @@ -1526,50 +1536,50 @@ 39 40 41 42 43>; #interrupt-cells = <1>; interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 421 0 0x0 0x0 0x0 1 &intc 0 142 0 0x0 0x0 0x0 2 &intc 0 143 0 0x0 0x0 0x0 3 &intc 0 144 0 0x0 0x0 0x0 4 &intc 0 145 0 0x0 0x0 0x0 5 &intc 0 146 0 0x0 0x0 0x0 6 &intc 0 147 0 0x0 0x0 0x0 7 &intc 0 148 0 0x0 0x0 0x0 8 &intc 0 149 0 0x0 0x0 0x0 9 &intc 0 260 0 0x0 0x0 0x0 10 &intc 0 261 0 0x0 0x0 0x0 11 &intc 0 262 0 0x0 0x0 0x0 12 &intc 0 576 0 0x0 0x0 0x0 13 &intc 0 577 0 0x0 0x0 0x0 14 &intc 0 578 0 0x0 0x0 0x0 15 &intc 0 579 0 0x0 0x0 0x0 16 &intc 0 580 0 0x0 0x0 0x0 17 &intc 0 581 0 0x0 0x0 0x0 18 &intc 0 582 0 0x0 0x0 0x0 19 &intc 0 583 0 0x0 0x0 0x0 20 &intc 0 584 0 0x0 0x0 0x0 21 &intc 0 585 0 0x0 0x0 0x0 22 &intc 0 586 0 0x0 0x0 0x0 23 &intc 0 587 0 0x0 0x0 0x0 24 &intc 0 588 0 0x0 0x0 0x0 25 &intc 0 589 0 0x0 0x0 0x0 26 &intc 0 590 0 0x0 0x0 0x0 27 &intc 0 591 0 0x0 0x0 0x0 28 &intc 0 592 0 0x0 0x0 0x0 29 &intc 0 593 0 0x0 0x0 0x0 30 &intc 0 594 0 0x0 0x0 0x0 31 &intc 0 595 0 0x0 0x0 0x0 32 &intc 0 596 0 0x0 0x0 0x0 33 &intc 0 597 0 0x0 0x0 0x0 34 &intc 0 598 0 0x0 0x0 0x0 35 &intc 0 599 0 0x0 0x0 0x0 36 &intc 0 600 0 0x0 0x0 0x0 37 &intc 0 601 0 0x0 0x0 0x0 38 &intc 0 602 0 0x0 0x0 0x0 39 &intc 0 603 0 0x0 0x0 0x0 40 &intc 0 604 0 0x0 0x0 0x0 41 &intc 0 605 0 0x0 0x0 0x0 42 &intc 0 606 0 0x0 0x0 0x0 43 &intc 0 607 0>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 421 0 0x0 0x0 0x0 1 &intc 0 0 142 0 0x0 0x0 0x0 2 &intc 0 0 143 0 0x0 0x0 0x0 3 &intc 0 0 144 0 0x0 0x0 0x0 4 &intc 0 0 145 0 0x0 0x0 0x0 5 &intc 0 0 146 0 0x0 0x0 0x0 6 &intc 0 0 147 0 0x0 0x0 0x0 7 &intc 0 0 148 0 0x0 0x0 0x0 8 &intc 0 0 149 0 0x0 0x0 0x0 9 &intc 0 0 260 0 0x0 0x0 0x0 10 &intc 0 0 261 0 0x0 0x0 0x0 11 &intc 0 0 262 0 0x0 0x0 0x0 12 &intc 0 0 576 0 0x0 0x0 0x0 13 &intc 0 0 577 0 0x0 0x0 0x0 14 &intc 0 0 578 0 0x0 0x0 0x0 15 &intc 0 0 579 0 0x0 0x0 0x0 16 &intc 0 0 580 0 0x0 0x0 0x0 17 &intc 0 0 581 0 0x0 0x0 0x0 18 &intc 0 0 582 0 0x0 0x0 0x0 19 &intc 0 0 583 0 0x0 0x0 0x0 20 &intc 0 0 584 0 0x0 0x0 0x0 21 &intc 0 0 585 0 0x0 0x0 0x0 22 &intc 0 0 586 0 0x0 0x0 0x0 23 &intc 0 0 587 0 0x0 0x0 0x0 24 &intc 0 0 588 0 0x0 0x0 0x0 25 &intc 0 0 589 0 0x0 0x0 0x0 26 &intc 0 0 590 0 0x0 0x0 0x0 27 &intc 0 0 591 0 0x0 0x0 0x0 28 &intc 0 0 592 0 0x0 0x0 0x0 29 &intc 0 0 593 0 0x0 0x0 0x0 30 &intc 0 0 594 0 0x0 0x0 0x0 31 &intc 0 0 595 0 0x0 0x0 0x0 32 &intc 0 0 596 0 0x0 0x0 0x0 33 &intc 0 0 597 0 0x0 0x0 0x0 34 &intc 0 0 598 0 0x0 0x0 0x0 35 &intc 0 0 599 0 0x0 0x0 0x0 36 &intc 0 0 600 0 0x0 0x0 0x0 37 &intc 0 0 601 0 0x0 0x0 0x0 38 &intc 0 0 602 0 0x0 0x0 0x0 39 &intc 0 0 603 0 0x0 0x0 0x0 40 &intc 0 0 604 0 0x0 0x0 0x0 41 &intc 0 0 605 0 0x0 0x0 0x0 42 &intc 0 0 606 0 0x0 0x0 0x0 43 &intc 0 0 607 0>; interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d", "int_pls_pme", "int_pme_legacy", "int_pls_err", Loading arch/arm/mach-iop13xx/msi.c +1 −1 Original line number Diff line number Diff line Loading @@ -153,7 +153,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) id = iop13xx_cpu_id(); msg.data = (id << IOP13XX_MU_MIMR_CORE_SELECT) | (irq & 0x7f); write_msi_msg(irq, &msg); pci_write_msi_msg(irq, &msg); irq_set_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq); return 0; Loading arch/arm64/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ config ARM64 select ARM_GIC select AUDIT_ARCH_COMPAT_GENERIC select ARM_GIC_V3 select ARM_GIC_V3_ITS if PCI_MSI select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS select COMMON_CLK if !ARCH_MSM Loading Loading
Documentation/IRQ-domain.txt +71 −0 Original line number Diff line number Diff line Loading @@ -151,3 +151,74 @@ used and no descriptor gets allocated it is very important to make sure that the driver using the simple domain call irq_create_mapping() before any irq_find_mapping() since the latter will actually work for the static IRQ assignment case. ==== Hierarchy IRQ domain ==== On some architectures, there may be multiple interrupt controllers involved in delivering an interrupt from the device to the target CPU. Let's look at a typical interrupt delivering path on x86 platforms: Device --> IOAPIC -> Interrupt remapping Controller -> Local APIC -> CPU There are three interrupt controllers involved: 1) IOAPIC controller 2) Interrupt remapping controller 3) Local APIC controller To support such a hardware topology and make software architecture match hardware architecture, an irq_domain data structure is built for each interrupt controller and those irq_domains are organized into hierarchy. When building irq_domain hierarchy, the irq_domain near to the device is child and the irq_domain near to CPU is parent. So a hierarchy structure as below will be built for the example above. CPU Vector irq_domain (root irq_domain to manage CPU vectors) ^ | Interrupt Remapping irq_domain (manage irq_remapping entries) ^ | IOAPIC irq_domain (manage IOAPIC delivery entries/pins) There are four major interfaces to use hierarchy irq_domain: 1) irq_domain_alloc_irqs(): allocate IRQ descriptors and interrupt controller related resources to deliver these interrupts. 2) irq_domain_free_irqs(): free IRQ descriptors and interrupt controller related resources associated with these interrupts. 3) irq_domain_activate_irq(): activate interrupt controller hardware to deliver the interrupt. 3) irq_domain_deactivate_irq(): deactivate interrupt controller hardware to stop delivering the interrupt. Following changes are needed to support hierarchy irq_domain. 1) a new field 'parent' is added to struct irq_domain; it's used to maintain irq_domain hierarchy information. 2) a new field 'parent_data' is added to struct irq_data; it's used to build hierarchy irq_data to match hierarchy irq_domains. The irq_data is used to store irq_domain pointer and hardware irq number. 3) new callbacks are added to struct irq_domain_ops to support hierarchy irq_domain operations. With support of hierarchy irq_domain and hierarchy irq_data ready, an irq_domain structure is built for each interrupt controller, and an irq_data structure is allocated for each irq_domain associated with an IRQ. Now we could go one step further to support stacked(hierarchy) irq_chip. That is, an irq_chip is associated with each irq_data along the hierarchy. A child irq_chip may implement a required action by itself or by cooperating with its parent irq_chip. With stacked irq_chip, interrupt controller driver only needs to deal with the hardware managed by itself and may ask for services from its parent irq_chip when needed. So we could achieve a much cleaner software architecture. For an interrupt controller driver to support hierarchy irq_domain, it needs to: 1) Implement irq_domain_ops.alloc and irq_domain_ops.free 2) Optionally implement irq_domain_ops.activate and irq_domain_ops.deactivate. 3) Optionally implement an irq_chip to manage the interrupt controller hardware. 4) No need to implement irq_domain_ops.map and irq_domain_ops.unmap, they are unused with hierarchy irq_domain. Hierarchy irq_domain may also be used to support other architectures, such as ARM, ARM64 etc.
Documentation/devicetree/bindings/arm/gic-v3.txt +39 −0 Original line number Diff line number Diff line Loading @@ -49,11 +49,29 @@ Optional occupied by the redistributors. Required if more than one such region is present. Sub-nodes: GICv3 has one or more Interrupt Translation Services (ITS) that are used to route Message Signalled Interrupts (MSI) to the CPUs. These nodes must have the following properties: - compatible : Should at least contain "arm,gic-v3-its". - msi-controller : Boolean property. Identifies the node as an MSI controller - reg: Specifies the base physical address and size of the ITS registers. The main GIC node must contain the appropriate #address-cells, #size-cells and ranges properties for the reg property of all ITS nodes. Examples: gic: interrupt-controller@2cf00000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; #address-cells = <2>; #size-cells = <2>; ranges; interrupt-controller; reg = <0x0 0x2f000000 0 0x10000>, // GICD <0x0 0x2f100000 0 0x200000>, // GICR Loading @@ -61,11 +79,20 @@ Examples: <0x0 0x2c010000 0 0x2000>, // GICH <0x0 0x2c020000 0 0x2000>; // GICV interrupts = <1 9 4>; gic-its@2c200000 { compatible = "arm,gic-v3-its"; msi-controller; reg = <0x0 0x2c200000 0 0x200000>; }; }; gic: interrupt-controller@2c010000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; #address-cells = <2>; #size-cells = <2>; ranges; interrupt-controller; redistributor-stride = <0x0 0x40000>; // 256kB stride #redistributor-regions = <2>; Loading @@ -76,4 +103,16 @@ Examples: <0x0 0x2c060000 0 0x2000>, // GICH <0x0 0x2c080000 0 0x2000>; // GICV interrupts = <1 9 4>; gic-its@2c200000 { compatible = "arm,gic-v3-its"; msi-controller; reg = <0x0 0x2c200000 0 0x200000>; }; gic-its@2c400000 { compatible = "arm,gic-v3-its"; msi-controller; reg = <0x0 0x2c400000 0 0x200000>; }; };
arch/arm/boot/dts/qcom/msm8996.dtsi +144 −134 Original line number Diff line number Diff line Loading @@ -250,13 +250,23 @@ intc: interrupt-controller@09bc0000 { compatible = "arm,gic-v3"; reg = <0x9bc0000 0x10000>, /* GICD */ <0x9c00000 0x100000>; /* GICR * 4 */ #interrupt-cells = <3>; #address-cells = <1>; #size-cells = <1>; ranges; interrupt-controller; #redistributor-regions = <1>; redistributor-stride = <0x0 0x40000>; reg = <0x09bc0000 0x10000>, /* GICD */ <0x09c00000 0x100000>; /* GICR * 4 */ interrupts = <1 9 4>; gic-its@09BE0000 { compatible = "arm,gic-v3-its"; msi-contoller; reg = <0x9be0000 0x20000>; }; }; timer { Loading Loading @@ -1222,50 +1232,50 @@ 39 40 41 42 43>; #interrupt-cells = <1>; interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 405 0 0x0 0x0 0x0 1 &intc 0 244 0 0x0 0x0 0x0 2 &intc 0 245 0 0x0 0x0 0x0 3 &intc 0 247 0 0x0 0x0 0x0 4 &intc 0 248 0 0x0 0x0 0x0 5 &intc 0 249 0 0x0 0x0 0x0 6 &intc 0 250 0 0x0 0x0 0x0 7 &intc 0 251 0 0x0 0x0 0x0 8 &intc 0 252 0 0x0 0x0 0x0 9 &intc 0 253 0 0x0 0x0 0x0 10 &intc 0 254 0 0x0 0x0 0x0 11 &intc 0 255 0 0x0 0x0 0x0 12 &intc 0 512 0 0x0 0x0 0x0 13 &intc 0 513 0 0x0 0x0 0x0 14 &intc 0 514 0 0x0 0x0 0x0 15 &intc 0 515 0 0x0 0x0 0x0 16 &intc 0 516 0 0x0 0x0 0x0 17 &intc 0 517 0 0x0 0x0 0x0 18 &intc 0 518 0 0x0 0x0 0x0 19 &intc 0 519 0 0x0 0x0 0x0 20 &intc 0 520 0 0x0 0x0 0x0 21 &intc 0 521 0 0x0 0x0 0x0 22 &intc 0 522 0 0x0 0x0 0x0 23 &intc 0 523 0 0x0 0x0 0x0 24 &intc 0 524 0 0x0 0x0 0x0 25 &intc 0 525 0 0x0 0x0 0x0 26 &intc 0 526 0 0x0 0x0 0x0 27 &intc 0 527 0 0x0 0x0 0x0 28 &intc 0 528 0 0x0 0x0 0x0 29 &intc 0 529 0 0x0 0x0 0x0 30 &intc 0 530 0 0x0 0x0 0x0 31 &intc 0 531 0 0x0 0x0 0x0 32 &intc 0 532 0 0x0 0x0 0x0 33 &intc 0 533 0 0x0 0x0 0x0 34 &intc 0 534 0 0x0 0x0 0x0 35 &intc 0 535 0 0x0 0x0 0x0 36 &intc 0 536 0 0x0 0x0 0x0 37 &intc 0 537 0 0x0 0x0 0x0 38 &intc 0 538 0 0x0 0x0 0x0 39 &intc 0 539 0 0x0 0x0 0x0 40 &intc 0 540 0 0x0 0x0 0x0 41 &intc 0 541 0 0x0 0x0 0x0 42 &intc 0 542 0 0x0 0x0 0x0 43 &intc 0 543 0>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 405 0 0x0 0x0 0x0 1 &intc 0 0 244 0 0x0 0x0 0x0 2 &intc 0 0 245 0 0x0 0x0 0x0 3 &intc 0 0 247 0 0x0 0x0 0x0 4 &intc 0 0 248 0 0x0 0x0 0x0 5 &intc 0 0 249 0 0x0 0x0 0x0 6 &intc 0 0 250 0 0x0 0x0 0x0 7 &intc 0 0 251 0 0x0 0x0 0x0 8 &intc 0 0 252 0 0x0 0x0 0x0 9 &intc 0 0 253 0 0x0 0x0 0x0 10 &intc 0 0 254 0 0x0 0x0 0x0 11 &intc 0 0 255 0 0x0 0x0 0x0 12 &intc 0 0 512 0 0x0 0x0 0x0 13 &intc 0 0 513 0 0x0 0x0 0x0 14 &intc 0 0 514 0 0x0 0x0 0x0 15 &intc 0 0 515 0 0x0 0x0 0x0 16 &intc 0 0 516 0 0x0 0x0 0x0 17 &intc 0 0 517 0 0x0 0x0 0x0 18 &intc 0 0 518 0 0x0 0x0 0x0 19 &intc 0 0 519 0 0x0 0x0 0x0 20 &intc 0 0 520 0 0x0 0x0 0x0 21 &intc 0 0 521 0 0x0 0x0 0x0 22 &intc 0 0 522 0 0x0 0x0 0x0 23 &intc 0 0 523 0 0x0 0x0 0x0 24 &intc 0 0 524 0 0x0 0x0 0x0 25 &intc 0 0 525 0 0x0 0x0 0x0 26 &intc 0 0 526 0 0x0 0x0 0x0 27 &intc 0 0 527 0 0x0 0x0 0x0 28 &intc 0 0 528 0 0x0 0x0 0x0 29 &intc 0 0 529 0 0x0 0x0 0x0 30 &intc 0 0 530 0 0x0 0x0 0x0 31 &intc 0 0 531 0 0x0 0x0 0x0 32 &intc 0 0 532 0 0x0 0x0 0x0 33 &intc 0 0 533 0 0x0 0x0 0x0 34 &intc 0 0 534 0 0x0 0x0 0x0 35 &intc 0 0 535 0 0x0 0x0 0x0 36 &intc 0 0 536 0 0x0 0x0 0x0 37 &intc 0 0 537 0 0x0 0x0 0x0 38 &intc 0 0 538 0 0x0 0x0 0x0 39 &intc 0 0 539 0 0x0 0x0 0x0 40 &intc 0 0 540 0 0x0 0x0 0x0 41 &intc 0 0 541 0 0x0 0x0 0x0 42 &intc 0 0 542 0 0x0 0x0 0x0 43 &intc 0 0 543 0>; interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d", "int_pls_pme", "int_pme_legacy", "int_pls_err", Loading Loading @@ -1376,50 +1386,50 @@ 39 40 41 42 43>; #interrupt-cells = <1>; interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 413 0 0x0 0x0 0x0 1 &intc 0 272 0 0x0 0x0 0x0 2 &intc 0 273 0 0x0 0x0 0x0 3 &intc 0 274 0 0x0 0x0 0x0 4 &intc 0 275 0 0x0 0x0 0x0 5 &intc 0 276 0 0x0 0x0 0x0 6 &intc 0 277 0 0x0 0x0 0x0 7 &intc 0 278 0 0x0 0x0 0x0 8 &intc 0 279 0 0x0 0x0 0x0 9 &intc 0 280 0 0x0 0x0 0x0 10 &intc 0 281 0 0x0 0x0 0x0 11 &intc 0 282 0 0x0 0x0 0x0 12 &intc 0 544 0 0x0 0x0 0x0 13 &intc 0 545 0 0x0 0x0 0x0 14 &intc 0 546 0 0x0 0x0 0x0 15 &intc 0 547 0 0x0 0x0 0x0 16 &intc 0 548 0 0x0 0x0 0x0 17 &intc 0 549 0 0x0 0x0 0x0 18 &intc 0 550 0 0x0 0x0 0x0 19 &intc 0 551 0 0x0 0x0 0x0 20 &intc 0 552 0 0x0 0x0 0x0 21 &intc 0 553 0 0x0 0x0 0x0 22 &intc 0 554 0 0x0 0x0 0x0 23 &intc 0 555 0 0x0 0x0 0x0 24 &intc 0 556 0 0x0 0x0 0x0 25 &intc 0 557 0 0x0 0x0 0x0 26 &intc 0 558 0 0x0 0x0 0x0 27 &intc 0 559 0 0x0 0x0 0x0 28 &intc 0 560 0 0x0 0x0 0x0 29 &intc 0 561 0 0x0 0x0 0x0 30 &intc 0 562 0 0x0 0x0 0x0 31 &intc 0 563 0 0x0 0x0 0x0 32 &intc 0 564 0 0x0 0x0 0x0 33 &intc 0 565 0 0x0 0x0 0x0 34 &intc 0 566 0 0x0 0x0 0x0 35 &intc 0 567 0 0x0 0x0 0x0 36 &intc 0 568 0 0x0 0x0 0x0 37 &intc 0 569 0 0x0 0x0 0x0 38 &intc 0 570 0 0x0 0x0 0x0 39 &intc 0 571 0 0x0 0x0 0x0 40 &intc 0 572 0 0x0 0x0 0x0 41 &intc 0 573 0 0x0 0x0 0x0 42 &intc 0 574 0 0x0 0x0 0x0 43 &intc 0 575 0>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 413 0 0x0 0x0 0x0 1 &intc 0 0 272 0 0x0 0x0 0x0 2 &intc 0 0 273 0 0x0 0x0 0x0 3 &intc 0 0 274 0 0x0 0x0 0x0 4 &intc 0 0 275 0 0x0 0x0 0x0 5 &intc 0 0 276 0 0x0 0x0 0x0 6 &intc 0 0 277 0 0x0 0x0 0x0 7 &intc 0 0 278 0 0x0 0x0 0x0 8 &intc 0 0 279 0 0x0 0x0 0x0 9 &intc 0 0 280 0 0x0 0x0 0x0 10 &intc 0 0 281 0 0x0 0x0 0x0 11 &intc 0 0 282 0 0x0 0x0 0x0 12 &intc 0 0 544 0 0x0 0x0 0x0 13 &intc 0 0 545 0 0x0 0x0 0x0 14 &intc 0 0 546 0 0x0 0x0 0x0 15 &intc 0 0 547 0 0x0 0x0 0x0 16 &intc 0 0 548 0 0x0 0x0 0x0 17 &intc 0 0 549 0 0x0 0x0 0x0 18 &intc 0 0 550 0 0x0 0x0 0x0 19 &intc 0 0 551 0 0x0 0x0 0x0 20 &intc 0 0 552 0 0x0 0x0 0x0 21 &intc 0 0 553 0 0x0 0x0 0x0 22 &intc 0 0 554 0 0x0 0x0 0x0 23 &intc 0 0 555 0 0x0 0x0 0x0 24 &intc 0 0 556 0 0x0 0x0 0x0 25 &intc 0 0 557 0 0x0 0x0 0x0 26 &intc 0 0 558 0 0x0 0x0 0x0 27 &intc 0 0 559 0 0x0 0x0 0x0 28 &intc 0 0 560 0 0x0 0x0 0x0 29 &intc 0 0 561 0 0x0 0x0 0x0 30 &intc 0 0 562 0 0x0 0x0 0x0 31 &intc 0 0 563 0 0x0 0x0 0x0 32 &intc 0 0 564 0 0x0 0x0 0x0 33 &intc 0 0 565 0 0x0 0x0 0x0 34 &intc 0 0 566 0 0x0 0x0 0x0 35 &intc 0 0 567 0 0x0 0x0 0x0 36 &intc 0 0 568 0 0x0 0x0 0x0 37 &intc 0 0 569 0 0x0 0x0 0x0 38 &intc 0 0 570 0 0x0 0x0 0x0 39 &intc 0 0 571 0 0x0 0x0 0x0 40 &intc 0 0 572 0 0x0 0x0 0x0 41 &intc 0 0 573 0 0x0 0x0 0x0 42 &intc 0 0 574 0 0x0 0x0 0x0 43 &intc 0 0 575 0>; interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d", "int_pls_pme", "int_pme_legacy", "int_pls_err", Loading Loading @@ -1526,50 +1536,50 @@ 39 40 41 42 43>; #interrupt-cells = <1>; interrupt-map-mask = <0x0 0x0 0x0 0xffffffff>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 421 0 0x0 0x0 0x0 1 &intc 0 142 0 0x0 0x0 0x0 2 &intc 0 143 0 0x0 0x0 0x0 3 &intc 0 144 0 0x0 0x0 0x0 4 &intc 0 145 0 0x0 0x0 0x0 5 &intc 0 146 0 0x0 0x0 0x0 6 &intc 0 147 0 0x0 0x0 0x0 7 &intc 0 148 0 0x0 0x0 0x0 8 &intc 0 149 0 0x0 0x0 0x0 9 &intc 0 260 0 0x0 0x0 0x0 10 &intc 0 261 0 0x0 0x0 0x0 11 &intc 0 262 0 0x0 0x0 0x0 12 &intc 0 576 0 0x0 0x0 0x0 13 &intc 0 577 0 0x0 0x0 0x0 14 &intc 0 578 0 0x0 0x0 0x0 15 &intc 0 579 0 0x0 0x0 0x0 16 &intc 0 580 0 0x0 0x0 0x0 17 &intc 0 581 0 0x0 0x0 0x0 18 &intc 0 582 0 0x0 0x0 0x0 19 &intc 0 583 0 0x0 0x0 0x0 20 &intc 0 584 0 0x0 0x0 0x0 21 &intc 0 585 0 0x0 0x0 0x0 22 &intc 0 586 0 0x0 0x0 0x0 23 &intc 0 587 0 0x0 0x0 0x0 24 &intc 0 588 0 0x0 0x0 0x0 25 &intc 0 589 0 0x0 0x0 0x0 26 &intc 0 590 0 0x0 0x0 0x0 27 &intc 0 591 0 0x0 0x0 0x0 28 &intc 0 592 0 0x0 0x0 0x0 29 &intc 0 593 0 0x0 0x0 0x0 30 &intc 0 594 0 0x0 0x0 0x0 31 &intc 0 595 0 0x0 0x0 0x0 32 &intc 0 596 0 0x0 0x0 0x0 33 &intc 0 597 0 0x0 0x0 0x0 34 &intc 0 598 0 0x0 0x0 0x0 35 &intc 0 599 0 0x0 0x0 0x0 36 &intc 0 600 0 0x0 0x0 0x0 37 &intc 0 601 0 0x0 0x0 0x0 38 &intc 0 602 0 0x0 0x0 0x0 39 &intc 0 603 0 0x0 0x0 0x0 40 &intc 0 604 0 0x0 0x0 0x0 41 &intc 0 605 0 0x0 0x0 0x0 42 &intc 0 606 0 0x0 0x0 0x0 43 &intc 0 607 0>; interrupt-map = <0x0 0x0 0x0 0 &intc 0 0 421 0 0x0 0x0 0x0 1 &intc 0 0 142 0 0x0 0x0 0x0 2 &intc 0 0 143 0 0x0 0x0 0x0 3 &intc 0 0 144 0 0x0 0x0 0x0 4 &intc 0 0 145 0 0x0 0x0 0x0 5 &intc 0 0 146 0 0x0 0x0 0x0 6 &intc 0 0 147 0 0x0 0x0 0x0 7 &intc 0 0 148 0 0x0 0x0 0x0 8 &intc 0 0 149 0 0x0 0x0 0x0 9 &intc 0 0 260 0 0x0 0x0 0x0 10 &intc 0 0 261 0 0x0 0x0 0x0 11 &intc 0 0 262 0 0x0 0x0 0x0 12 &intc 0 0 576 0 0x0 0x0 0x0 13 &intc 0 0 577 0 0x0 0x0 0x0 14 &intc 0 0 578 0 0x0 0x0 0x0 15 &intc 0 0 579 0 0x0 0x0 0x0 16 &intc 0 0 580 0 0x0 0x0 0x0 17 &intc 0 0 581 0 0x0 0x0 0x0 18 &intc 0 0 582 0 0x0 0x0 0x0 19 &intc 0 0 583 0 0x0 0x0 0x0 20 &intc 0 0 584 0 0x0 0x0 0x0 21 &intc 0 0 585 0 0x0 0x0 0x0 22 &intc 0 0 586 0 0x0 0x0 0x0 23 &intc 0 0 587 0 0x0 0x0 0x0 24 &intc 0 0 588 0 0x0 0x0 0x0 25 &intc 0 0 589 0 0x0 0x0 0x0 26 &intc 0 0 590 0 0x0 0x0 0x0 27 &intc 0 0 591 0 0x0 0x0 0x0 28 &intc 0 0 592 0 0x0 0x0 0x0 29 &intc 0 0 593 0 0x0 0x0 0x0 30 &intc 0 0 594 0 0x0 0x0 0x0 31 &intc 0 0 595 0 0x0 0x0 0x0 32 &intc 0 0 596 0 0x0 0x0 0x0 33 &intc 0 0 597 0 0x0 0x0 0x0 34 &intc 0 0 598 0 0x0 0x0 0x0 35 &intc 0 0 599 0 0x0 0x0 0x0 36 &intc 0 0 600 0 0x0 0x0 0x0 37 &intc 0 0 601 0 0x0 0x0 0x0 38 &intc 0 0 602 0 0x0 0x0 0x0 39 &intc 0 0 603 0 0x0 0x0 0x0 40 &intc 0 0 604 0 0x0 0x0 0x0 41 &intc 0 0 605 0 0x0 0x0 0x0 42 &intc 0 0 606 0 0x0 0x0 0x0 43 &intc 0 0 607 0>; interrupt-names = "int_msi", "int_a", "int_b", "int_c", "int_d", "int_pls_pme", "int_pme_legacy", "int_pls_err", Loading
arch/arm/mach-iop13xx/msi.c +1 −1 Original line number Diff line number Diff line Loading @@ -153,7 +153,7 @@ int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) id = iop13xx_cpu_id(); msg.data = (id << IOP13XX_MU_MIMR_CORE_SELECT) | (irq & 0x7f); write_msi_msg(irq, &msg); pci_write_msi_msg(irq, &msg); irq_set_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq); return 0; Loading
arch/arm64/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ config ARM64 select ARM_GIC select AUDIT_ARCH_COMPAT_GENERIC select ARM_GIC_V3 select ARM_GIC_V3_ITS if PCI_MSI select BUILDTIME_EXTABLE_SORT select CLONE_BACKWARDS select COMMON_CLK if !ARCH_MSM Loading