Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'irq-core-2022-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq updates from Thomas Gleixner:
"Updates for interrupt core and drivers:

Core:

- Fix a few inconsistencies between UP and SMP vs interrupt
affinities

- Small updates and cleanups all over the place

New drivers:

- LoongArch interrupt controller

- Renesas RZ/G2L interrupt controller

Updates:

- Hotpath optimization for SiFive PLIC

- Workaround for broken PLIC edge triggered interrupts

- Simall cleanups and improvements as usual"

* tag 'irq-core-2022-08-01' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (52 commits)
irqchip/mmp: Declare init functions in common header file
irqchip/mips-gic: Check the return value of ioremap() in gic_of_init()
genirq: Use for_each_action_of_desc in actions_show()
irqchip / ACPI: Introduce ACPI_IRQ_MODEL_LPIC for LoongArch
irqchip: Add LoongArch CPU interrupt controller support
irqchip: Add Loongson Extended I/O interrupt controller support
irqchip/loongson-liointc: Add ACPI init support
irqchip/loongson-pch-msi: Add ACPI init support
irqchip/loongson-pch-pic: Add ACPI init support
irqchip: Add Loongson PCH LPC controller support
LoongArch: Prepare to support multiple pch-pic and pch-msi irqdomain
LoongArch: Use ACPI_GENERIC_GSI for gsi handling
genirq/generic_chip: Export irq_unmap_generic_chip
ACPI: irq: Allow acpi_gsi_to_irq() to have an arch-specific fallback
APCI: irq: Add support for multiple GSI domains
LoongArch: Provisionally add ACPICA data structures
irqdomain: Use hwirq_max instead of revmap_size for NOMAP domains
irqdomain: Report irq number for NOMAP domains
irqchip/gic-v3: Fix comment typo
dt-bindings: interrupt-controller: renesas,rzg2l-irqc: Document RZ/V2L SoC
...

+2784 -667
+134
Documentation/devicetree/bindings/interrupt-controller/renesas,rzg2l-irqc.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/interrupt-controller/renesas,rzg2l-irqc.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Renesas RZ/G2L (and alike SoC's) Interrupt Controller (IA55) 8 + 9 + maintainers: 10 + - Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> 11 + - Geert Uytterhoeven <geert+renesas@glider.be> 12 + 13 + description: | 14 + IA55 performs various interrupt controls including synchronization for the external 15 + interrupts of NMI, IRQ, and GPIOINT and the interrupts of the built-in peripheral 16 + interrupts output by each IP. And it notifies the interrupt to the GIC 17 + - IRQ sense select for 8 external interrupts, mapped to 8 GIC SPI interrupts 18 + - GPIO pins used as external interrupt input pins, mapped to 32 GIC SPI interrupts 19 + - NMI edge select (NMI is not treated as NMI exception and supports fall edge and 20 + stand-up edge detection interrupts) 21 + 22 + allOf: 23 + - $ref: /schemas/interrupt-controller.yaml# 24 + 25 + properties: 26 + compatible: 27 + items: 28 + - enum: 29 + - renesas,r9a07g044-irqc # RZ/G2{L,LC} 30 + - renesas,r9a07g054-irqc # RZ/V2L 31 + - const: renesas,rzg2l-irqc 32 + 33 + '#interrupt-cells': 34 + description: The first cell should contain external interrupt number (IRQ0-7) and the 35 + second cell is used to specify the flag. 36 + const: 2 37 + 38 + '#address-cells': 39 + const: 0 40 + 41 + interrupt-controller: true 42 + 43 + reg: 44 + maxItems: 1 45 + 46 + interrupts: 47 + maxItems: 41 48 + 49 + clocks: 50 + maxItems: 2 51 + 52 + clock-names: 53 + items: 54 + - const: clk 55 + - const: pclk 56 + 57 + power-domains: 58 + maxItems: 1 59 + 60 + resets: 61 + maxItems: 1 62 + 63 + required: 64 + - compatible 65 + - '#interrupt-cells' 66 + - '#address-cells' 67 + - interrupt-controller 68 + - reg 69 + - interrupts 70 + - clocks 71 + - clock-names 72 + - power-domains 73 + - resets 74 + 75 + unevaluatedProperties: false 76 + 77 + examples: 78 + - | 79 + #include <dt-bindings/interrupt-controller/arm-gic.h> 80 + #include <dt-bindings/clock/r9a07g044-cpg.h> 81 + 82 + irqc: interrupt-controller@110a0000 { 83 + compatible = "renesas,r9a07g044-irqc", "renesas,rzg2l-irqc"; 84 + reg = <0x110a0000 0x10000>; 85 + #interrupt-cells = <2>; 86 + #address-cells = <0>; 87 + interrupt-controller; 88 + interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>, 89 + <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>, 90 + <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>, 91 + <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, 92 + <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>, 93 + <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>, 94 + <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>, 95 + <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, 96 + <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, 97 + <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>, 98 + <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>, 99 + <GIC_SPI 446 IRQ_TYPE_LEVEL_HIGH>, 100 + <GIC_SPI 447 IRQ_TYPE_LEVEL_HIGH>, 101 + <GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, 102 + <GIC_SPI 449 IRQ_TYPE_LEVEL_HIGH>, 103 + <GIC_SPI 450 IRQ_TYPE_LEVEL_HIGH>, 104 + <GIC_SPI 451 IRQ_TYPE_LEVEL_HIGH>, 105 + <GIC_SPI 452 IRQ_TYPE_LEVEL_HIGH>, 106 + <GIC_SPI 453 IRQ_TYPE_LEVEL_HIGH>, 107 + <GIC_SPI 454 IRQ_TYPE_LEVEL_HIGH>, 108 + <GIC_SPI 455 IRQ_TYPE_LEVEL_HIGH>, 109 + <GIC_SPI 456 IRQ_TYPE_LEVEL_HIGH>, 110 + <GIC_SPI 457 IRQ_TYPE_LEVEL_HIGH>, 111 + <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH>, 112 + <GIC_SPI 459 IRQ_TYPE_LEVEL_HIGH>, 113 + <GIC_SPI 460 IRQ_TYPE_LEVEL_HIGH>, 114 + <GIC_SPI 461 IRQ_TYPE_LEVEL_HIGH>, 115 + <GIC_SPI 462 IRQ_TYPE_LEVEL_HIGH>, 116 + <GIC_SPI 463 IRQ_TYPE_LEVEL_HIGH>, 117 + <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, 118 + <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, 119 + <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, 120 + <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, 121 + <GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, 122 + <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>, 123 + <GIC_SPI 470 IRQ_TYPE_LEVEL_HIGH>, 124 + <GIC_SPI 471 IRQ_TYPE_LEVEL_HIGH>, 125 + <GIC_SPI 472 IRQ_TYPE_LEVEL_HIGH>, 126 + <GIC_SPI 473 IRQ_TYPE_LEVEL_HIGH>, 127 + <GIC_SPI 474 IRQ_TYPE_LEVEL_HIGH>, 128 + <GIC_SPI 475 IRQ_TYPE_LEVEL_HIGH>; 129 + clocks = <&cpg CPG_MOD R9A07G044_IA55_CLK>, 130 + <&cpg CPG_MOD R9A07G044_IA55_PCLK>; 131 + clock-names = "clk", "pclk"; 132 + power-domains = <&cpg>; 133 + resets = <&cpg R9A07G044_IA55_RESETN>; 134 + };
+60 -5
Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml
··· 26 26 with priority below this threshold will not cause the PLIC to raise its 27 27 interrupt line leading to the context. 28 28 29 - While the PLIC supports both edge-triggered and level-triggered interrupts, 30 - interrupt handlers are oblivious to this distinction and therefore it is not 31 - specified in the PLIC device-tree binding. 29 + The PLIC supports both edge-triggered and level-triggered interrupts. For 30 + edge-triggered interrupts, the RISC-V PLIC spec allows two responses to edges 31 + seen while an interrupt handler is active; the PLIC may either queue them or 32 + ignore them. In the first case, handlers are oblivious to the trigger type, so 33 + it is not included in the interrupt specifier. In the second case, software 34 + needs to know the trigger type, so it can reorder the interrupt flow to avoid 35 + missing interrupts. This special handling is needed by at least the Renesas 36 + RZ/Five SoC (AX45MP AndesCore with a NCEPLIC100) and the T-HEAD C900 PLIC. 32 37 33 38 While the RISC-V ISA doesn't specify a memory layout for the PLIC, the 34 39 "sifive,plic-1.0.0" device is a concrete implementation of the PLIC that ··· 54 49 oneOf: 55 50 - items: 56 51 - enum: 52 + - renesas,r9a07g043-plic 53 + - const: andestech,nceplic100 54 + - items: 55 + - enum: 57 56 - sifive,fu540-c000-plic 58 57 - starfive,jh7100-plic 59 58 - canaan,k210-plic ··· 73 64 '#address-cells': 74 65 const: 0 75 66 76 - '#interrupt-cells': 77 - const: 1 67 + '#interrupt-cells': true 78 68 79 69 interrupt-controller: true 80 70 ··· 90 82 description: 91 83 Specifies how many external interrupts are supported by this controller. 92 84 85 + clocks: true 86 + 87 + power-domains: true 88 + 89 + resets: true 90 + 93 91 required: 94 92 - compatible 95 93 - '#address-cells' ··· 104 90 - reg 105 91 - interrupts-extended 106 92 - riscv,ndev 93 + 94 + allOf: 95 + - if: 96 + properties: 97 + compatible: 98 + contains: 99 + enum: 100 + - andestech,nceplic100 101 + - thead,c900-plic 102 + 103 + then: 104 + properties: 105 + '#interrupt-cells': 106 + const: 2 107 + 108 + else: 109 + properties: 110 + '#interrupt-cells': 111 + const: 1 112 + 113 + - if: 114 + properties: 115 + compatible: 116 + contains: 117 + const: renesas,r9a07g043-plic 118 + 119 + then: 120 + properties: 121 + clocks: 122 + maxItems: 1 123 + 124 + power-domains: 125 + maxItems: 1 126 + 127 + resets: 128 + maxItems: 1 129 + 130 + required: 131 + - clocks 132 + - power-domains 133 + - resets 107 134 108 135 additionalProperties: false 109 136
+15
Documentation/devicetree/bindings/pinctrl/renesas,rzg2l-pinctrl.yaml
··· 47 47 gpio-ranges: 48 48 maxItems: 1 49 49 50 + interrupt-controller: true 51 + 52 + '#interrupt-cells': 53 + const: 2 54 + description: 55 + The first cell contains the global GPIO port index, constructed using the 56 + RZG2L_GPIO() helper macro in <dt-bindings/pinctrl/rzg2l-pinctrl.h> and the 57 + second cell is used to specify the flag. 58 + E.g. "interrupts = <RZG2L_GPIO(43, 0) IRQ_TYPE_EDGE_FALLING>;" if P43_0 is 59 + being used as an interrupt. 60 + 50 61 clocks: 51 62 maxItems: 1 52 63 ··· 121 110 - gpio-controller 122 111 - '#gpio-cells' 123 112 - gpio-ranges 113 + - interrupt-controller 114 + - '#interrupt-cells' 124 115 - clocks 125 116 - power-domains 126 117 - resets ··· 139 126 gpio-controller; 140 127 #gpio-cells = <2>; 141 128 gpio-ranges = <&pinctrl 0 0 392>; 129 + interrupt-controller; 130 + #interrupt-cells = <2>; 142 131 clocks = <&cpg CPG_MOD R9A07G044_GPIO_HCLK>; 143 132 resets = <&cpg R9A07G044_GPIO_RSTN>, 144 133 <&cpg R9A07G044_GPIO_PORT_RESETN>,
+1 -1
arch/alpha/kernel/irq.c
··· 60 60 cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0); 61 61 last_cpu = cpu; 62 62 63 - cpumask_copy(irq_data_get_affinity_mask(data), cpumask_of(cpu)); 63 + irq_data_update_affinity(data, cpumask_of(cpu)); 64 64 chip->irq_set_affinity(data, cpumask_of(cpu), false); 65 65 return 0; 66 66 }
+1 -1
arch/arm/mach-hisi/Kconfig
··· 40 40 select HAVE_ARM_ARCH_TIMER 41 41 select MCPM if SMP 42 42 select MCPM_QUAD_CLUSTER if SMP 43 - select GENERIC_IRQ_EFFECTIVE_AFF_MASK 43 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 44 44 help 45 45 Support for Hisilicon HiP04 SoC family 46 46
+1 -1
arch/arm/mach-mmp/mmp2.h
··· 5 5 #include <linux/platform_data/pxa_sdhci.h> 6 6 7 7 extern void mmp2_timer_init(void); 8 - extern void __init mmp2_init_icu(void); 9 8 extern void __init mmp2_init_irq(void); 10 9 extern void mmp2_clear_pmic_int(void); 11 10 12 11 #include <linux/i2c.h> 13 12 #include <linux/platform_data/i2c-pxa.h> 14 13 #include <linux/platform_data/dma-mmp_tdma.h> 14 + #include <linux/irqchip/mmp.h> 15 15 16 16 #include "devices.h" 17 17
+1 -1
arch/arm/mach-mmp/pxa168.h
··· 5 5 #include <linux/reboot.h> 6 6 7 7 extern void pxa168_timer_init(void); 8 - extern void __init icu_init_irq(void); 9 8 extern void __init pxa168_init_irq(void); 10 9 extern void pxa168_restart(enum reboot_mode, const char *); 11 10 extern void pxa168_clear_keypad_wakeup(void); ··· 17 18 #include <linux/pxa168_eth.h> 18 19 #include <linux/platform_data/mv_usb.h> 19 20 #include <linux/soc/mmp/cputype.h> 21 + #include <linux/irqchip/mmp.h> 20 22 21 23 #include "devices.h" 22 24
+1 -1
arch/arm/mach-mmp/pxa910.h
··· 3 3 #define __ASM_MACH_PXA910_H 4 4 5 5 extern void pxa910_timer_init(void); 6 - extern void __init icu_init_irq(void); 7 6 extern void __init pxa910_init_irq(void); 8 7 9 8 #include <linux/i2c.h> 10 9 #include <linux/platform_data/i2c-pxa.h> 11 10 #include <linux/platform_data/mtd-nand-pxa3xx.h> 12 11 #include <video/mmp_disp.h> 12 + #include <linux/irqchip/mmp.h> 13 13 14 14 #include "devices.h" 15 15
+1 -1
arch/ia64/kernel/iosapic.c
··· 834 834 if (iosapic_intr_info[irq].count == 0) { 835 835 #ifdef CONFIG_SMP 836 836 /* Clear affinity */ 837 - cpumask_setall(irq_get_affinity_mask(irq)); 837 + irq_data_update_affinity(irq_get_irq_data(irq), cpu_all_mask); 838 838 #endif 839 839 /* Clear the interrupt information */ 840 840 iosapic_intr_info[irq].dest = 0;
+2 -2
arch/ia64/kernel/irq.c
··· 57 57 void set_irq_affinity_info (unsigned int irq, int hwid, int redir) 58 58 { 59 59 if (irq < NR_IRQS) { 60 - cpumask_copy(irq_get_affinity_mask(irq), 61 - cpumask_of(cpu_logical_id(hwid))); 60 + irq_data_update_affinity(irq_get_irq_data(irq), 61 + cpumask_of(cpu_logical_id(hwid))); 62 62 irq_redir[irq] = (char) (redir & 0xff); 63 63 } 64 64 }
+2 -2
arch/ia64/kernel/msi_ia64.c
··· 37 37 msg.data = data; 38 38 39 39 pci_write_msi_msg(irq, &msg); 40 - cpumask_copy(irq_data_get_affinity_mask(idata), cpumask_of(cpu)); 40 + irq_data_update_affinity(idata, cpumask_of(cpu)); 41 41 42 42 return 0; 43 43 } ··· 132 132 msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu)); 133 133 134 134 dmar_msi_write(irq, &msg); 135 - cpumask_copy(irq_data_get_affinity_mask(data), mask); 135 + irq_data_update_affinity(data, mask); 136 136 137 137 return 0; 138 138 }
+1
arch/loongarch/Kconfig
··· 2 2 config LOONGARCH 3 3 bool 4 4 default y 5 + select ACPI_GENERIC_GSI if ACPI 5 6 select ACPI_SYSTEM_POWER_STATES_SUPPORT if ACPI 6 7 select ARCH_BINFMT_ELF_STATE 7 8 select ARCH_ENABLE_MEMORY_HOTPLUG
+142
arch/loongarch/include/asm/acpi.h
··· 31 31 32 32 extern struct list_head acpi_wakeup_device_list; 33 33 34 + /* 35 + * Temporary definitions until the core ACPICA code gets updated (see 36 + * 1656837932-18257-1-git-send-email-lvjianmin@loongson.cn and its 37 + * follow-ups for the "rationale"). 38 + * 39 + * Once the "legal reasons" are cleared and that the code is merged, 40 + * this can be dropped entierely. 41 + */ 42 + #if (ACPI_CA_VERSION == 0x20220331 && !defined(LOONGARCH_ACPICA_EXT)) 43 + 44 + #define LOONGARCH_ACPICA_EXT 1 45 + 46 + #define ACPI_MADT_TYPE_CORE_PIC 17 47 + #define ACPI_MADT_TYPE_LIO_PIC 18 48 + #define ACPI_MADT_TYPE_HT_PIC 19 49 + #define ACPI_MADT_TYPE_EIO_PIC 20 50 + #define ACPI_MADT_TYPE_MSI_PIC 21 51 + #define ACPI_MADT_TYPE_BIO_PIC 22 52 + #define ACPI_MADT_TYPE_LPC_PIC 23 53 + 54 + /* Values for Version field above */ 55 + 56 + enum acpi_madt_core_pic_version { 57 + ACPI_MADT_CORE_PIC_VERSION_NONE = 0, 58 + ACPI_MADT_CORE_PIC_VERSION_V1 = 1, 59 + ACPI_MADT_CORE_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ 60 + }; 61 + 62 + enum acpi_madt_lio_pic_version { 63 + ACPI_MADT_LIO_PIC_VERSION_NONE = 0, 64 + ACPI_MADT_LIO_PIC_VERSION_V1 = 1, 65 + ACPI_MADT_LIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ 66 + }; 67 + 68 + enum acpi_madt_eio_pic_version { 69 + ACPI_MADT_EIO_PIC_VERSION_NONE = 0, 70 + ACPI_MADT_EIO_PIC_VERSION_V1 = 1, 71 + ACPI_MADT_EIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ 72 + }; 73 + 74 + enum acpi_madt_ht_pic_version { 75 + ACPI_MADT_HT_PIC_VERSION_NONE = 0, 76 + ACPI_MADT_HT_PIC_VERSION_V1 = 1, 77 + ACPI_MADT_HT_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ 78 + }; 79 + 80 + enum acpi_madt_bio_pic_version { 81 + ACPI_MADT_BIO_PIC_VERSION_NONE = 0, 82 + ACPI_MADT_BIO_PIC_VERSION_V1 = 1, 83 + ACPI_MADT_BIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ 84 + }; 85 + 86 + enum acpi_madt_msi_pic_version { 87 + ACPI_MADT_MSI_PIC_VERSION_NONE = 0, 88 + ACPI_MADT_MSI_PIC_VERSION_V1 = 1, 89 + ACPI_MADT_MSI_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ 90 + }; 91 + 92 + enum acpi_madt_lpc_pic_version { 93 + ACPI_MADT_LPC_PIC_VERSION_NONE = 0, 94 + ACPI_MADT_LPC_PIC_VERSION_V1 = 1, 95 + ACPI_MADT_LPC_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ 96 + }; 97 + 98 + #pragma pack(1) 99 + 100 + /* Core Interrupt Controller */ 101 + 102 + struct acpi_madt_core_pic { 103 + struct acpi_subtable_header header; 104 + u8 version; 105 + u32 processor_id; 106 + u32 core_id; 107 + u32 flags; 108 + }; 109 + 110 + /* Legacy I/O Interrupt Controller */ 111 + 112 + struct acpi_madt_lio_pic { 113 + struct acpi_subtable_header header; 114 + u8 version; 115 + u64 address; 116 + u16 size; 117 + u8 cascade[2]; 118 + u32 cascade_map[2]; 119 + }; 120 + 121 + /* Extend I/O Interrupt Controller */ 122 + 123 + struct acpi_madt_eio_pic { 124 + struct acpi_subtable_header header; 125 + u8 version; 126 + u8 cascade; 127 + u8 node; 128 + u64 node_map; 129 + }; 130 + 131 + /* HT Interrupt Controller */ 132 + 133 + struct acpi_madt_ht_pic { 134 + struct acpi_subtable_header header; 135 + u8 version; 136 + u64 address; 137 + u16 size; 138 + u8 cascade[8]; 139 + }; 140 + 141 + /* Bridge I/O Interrupt Controller */ 142 + 143 + struct acpi_madt_bio_pic { 144 + struct acpi_subtable_header header; 145 + u8 version; 146 + u64 address; 147 + u16 size; 148 + u16 id; 149 + u16 gsi_base; 150 + }; 151 + 152 + /* MSI Interrupt Controller */ 153 + 154 + struct acpi_madt_msi_pic { 155 + struct acpi_subtable_header header; 156 + u8 version; 157 + u64 msg_address; 158 + u32 start; 159 + u32 count; 160 + }; 161 + 162 + /* LPC Interrupt Controller */ 163 + 164 + struct acpi_madt_lpc_pic { 165 + struct acpi_subtable_header header; 166 + u8 version; 167 + u64 address; 168 + u16 size; 169 + u8 cascade; 170 + }; 171 + 172 + #pragma pack() 173 + 174 + #endif 175 + 34 176 #endif /* !CONFIG_ACPI */ 35 177 36 178 #define ACPI_TABLE_UPGRADE_MAX_PHYS ARCH_LOW_ADDRESS_LIMIT
+27 -24
arch/loongarch/include/asm/irq.h
··· 35 35 return (low <= sp && sp <= high); 36 36 } 37 37 38 - int get_ipi_irq(void); 39 - int get_pmc_irq(void); 40 - int get_timer_irq(void); 41 38 void spurious_interrupt(void); 42 39 43 40 #define NR_IRQS_LEGACY 16 ··· 44 47 45 48 #define MAX_IO_PICS 2 46 49 #define NR_IRQS (64 + (256 * MAX_IO_PICS)) 50 + 51 + struct acpi_vector_group { 52 + int node; 53 + int pci_segment; 54 + struct irq_domain *parent; 55 + }; 56 + extern struct acpi_vector_group pch_group[MAX_IO_PICS]; 57 + extern struct acpi_vector_group msi_group[MAX_IO_PICS]; 47 58 48 59 #define CORES_PER_EIO_NODE 4 49 60 ··· 84 79 extern int find_pch_pic(u32 gsi); 85 80 extern int eiointc_get_node(int id); 86 81 87 - static inline void eiointc_enable(void) 88 - { 89 - uint64_t misc; 90 - 91 - misc = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC); 92 - misc |= IOCSR_MISC_FUNC_EXT_IOI_EN; 93 - iocsr_write64(misc, LOONGARCH_IOCSR_MISC_FUNC); 94 - } 95 - 96 82 struct acpi_madt_lio_pic; 97 83 struct acpi_madt_eio_pic; 98 84 struct acpi_madt_ht_pic; ··· 91 95 struct acpi_madt_msi_pic; 92 96 struct acpi_madt_lpc_pic; 93 97 94 - struct irq_domain *loongarch_cpu_irq_init(void); 95 - 96 - struct irq_domain *liointc_acpi_init(struct irq_domain *parent, 98 + int liointc_acpi_init(struct irq_domain *parent, 97 99 struct acpi_madt_lio_pic *acpi_liointc); 98 - struct irq_domain *eiointc_acpi_init(struct irq_domain *parent, 100 + int eiointc_acpi_init(struct irq_domain *parent, 99 101 struct acpi_madt_eio_pic *acpi_eiointc); 100 102 101 103 struct irq_domain *htvec_acpi_init(struct irq_domain *parent, 102 104 struct acpi_madt_ht_pic *acpi_htvec); 103 - struct irq_domain *pch_lpc_acpi_init(struct irq_domain *parent, 105 + int pch_lpc_acpi_init(struct irq_domain *parent, 104 106 struct acpi_madt_lpc_pic *acpi_pchlpc); 105 - struct irq_domain *pch_msi_acpi_init(struct irq_domain *parent, 107 + #if IS_ENABLED(CONFIG_LOONGSON_PCH_MSI) 108 + int pch_msi_acpi_init(struct irq_domain *parent, 106 109 struct acpi_madt_msi_pic *acpi_pchmsi); 107 - struct irq_domain *pch_pic_acpi_init(struct irq_domain *parent, 110 + #else 111 + static inline int pch_msi_acpi_init(struct irq_domain *parent, 112 + struct acpi_madt_msi_pic *acpi_pchmsi) 113 + { 114 + return 0; 115 + } 116 + #endif 117 + int pch_pic_acpi_init(struct irq_domain *parent, 108 118 struct acpi_madt_bio_pic *acpi_pchpic); 119 + int find_pch_pic(u32 gsi); 120 + struct fwnode_handle *get_pch_msi_handle(int pci_segment); 109 121 110 122 extern struct acpi_madt_lio_pic *acpi_liointc; 111 123 extern struct acpi_madt_eio_pic *acpi_eiointc[MAX_IO_PICS]; ··· 123 119 extern struct acpi_madt_msi_pic *acpi_pchmsi[MAX_IO_PICS]; 124 120 extern struct acpi_madt_bio_pic *acpi_pchpic[MAX_IO_PICS]; 125 121 126 - extern struct irq_domain *cpu_domain; 127 - extern struct irq_domain *liointc_domain; 128 - extern struct irq_domain *pch_lpc_domain; 129 - extern struct irq_domain *pch_msi_domain[MAX_IO_PICS]; 130 - extern struct irq_domain *pch_pic_domain[MAX_IO_PICS]; 122 + extern struct fwnode_handle *cpuintc_handle; 123 + extern struct fwnode_handle *liointc_handle; 124 + extern struct fwnode_handle *pch_lpc_handle; 125 + extern struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; 131 126 132 127 extern irqreturn_t loongson3_ipi_interrupt(int irq, void *dev); 133 128
-65
arch/loongarch/kernel/acpi.c
··· 25 25 int acpi_strict = 1; /* We have no workarounds on LoongArch */ 26 26 int num_processors; 27 27 int disabled_cpus; 28 - enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM; 29 28 30 29 u64 acpi_saved_sp; 31 30 32 31 #define MAX_CORE_PIC 256 33 32 34 33 #define PREFIX "ACPI: " 35 - 36 - int acpi_gsi_to_irq(u32 gsi, unsigned int *irqp) 37 - { 38 - if (irqp != NULL) 39 - *irqp = acpi_register_gsi(NULL, gsi, -1, -1); 40 - return (*irqp >= 0) ? 0 : -EINVAL; 41 - } 42 - EXPORT_SYMBOL_GPL(acpi_gsi_to_irq); 43 - 44 - int acpi_isa_irq_to_gsi(unsigned int isa_irq, u32 *gsi) 45 - { 46 - if (gsi) 47 - *gsi = isa_irq; 48 - return 0; 49 - } 50 - 51 - /* 52 - * success: return IRQ number (>=0) 53 - * failure: return < 0 54 - */ 55 - int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, int polarity) 56 - { 57 - struct irq_fwspec fwspec; 58 - 59 - switch (gsi) { 60 - case GSI_MIN_CPU_IRQ ... GSI_MAX_CPU_IRQ: 61 - fwspec.fwnode = liointc_domain->fwnode; 62 - fwspec.param[0] = gsi - GSI_MIN_CPU_IRQ; 63 - fwspec.param_count = 1; 64 - 65 - return irq_create_fwspec_mapping(&fwspec); 66 - 67 - case GSI_MIN_LPC_IRQ ... GSI_MAX_LPC_IRQ: 68 - if (!pch_lpc_domain) 69 - return -EINVAL; 70 - 71 - fwspec.fwnode = pch_lpc_domain->fwnode; 72 - fwspec.param[0] = gsi - GSI_MIN_LPC_IRQ; 73 - fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity); 74 - fwspec.param_count = 2; 75 - 76 - return irq_create_fwspec_mapping(&fwspec); 77 - 78 - case GSI_MIN_PCH_IRQ ... GSI_MAX_PCH_IRQ: 79 - if (!pch_pic_domain[0]) 80 - return -EINVAL; 81 - 82 - fwspec.fwnode = pch_pic_domain[0]->fwnode; 83 - fwspec.param[0] = gsi - GSI_MIN_PCH_IRQ; 84 - fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; 85 - fwspec.param_count = 2; 86 - 87 - return irq_create_fwspec_mapping(&fwspec); 88 - } 89 - 90 - return -EINVAL; 91 - } 92 - EXPORT_SYMBOL_GPL(acpi_register_gsi); 93 - 94 - void acpi_unregister_gsi(u32 gsi) 95 - { 96 - 97 - } 98 - EXPORT_SYMBOL_GPL(acpi_unregister_gsi); 99 34 100 35 void __init __iomem * __acpi_map_table(unsigned long phys, unsigned long size) 101 36 {
+51 -7
arch/loongarch/kernel/irq.c
··· 25 25 DEFINE_PER_CPU_SHARED_ALIGNED(irq_cpustat_t, irq_stat); 26 26 EXPORT_PER_CPU_SYMBOL(irq_stat); 27 27 28 - struct irq_domain *cpu_domain; 29 - struct irq_domain *liointc_domain; 30 - struct irq_domain *pch_lpc_domain; 31 - struct irq_domain *pch_msi_domain[MAX_IO_PICS]; 32 - struct irq_domain *pch_pic_domain[MAX_IO_PICS]; 33 - 28 + struct acpi_vector_group pch_group[MAX_IO_PICS]; 29 + struct acpi_vector_group msi_group[MAX_IO_PICS]; 34 30 /* 35 31 * 'what should we do if we get a hw irq event on an illegal vector'. 36 32 * each architecture has to answer this themselves. ··· 52 56 return 0; 53 57 } 54 58 59 + static int __init early_pci_mcfg_parse(struct acpi_table_header *header) 60 + { 61 + struct acpi_table_mcfg *mcfg; 62 + struct acpi_mcfg_allocation *mptr; 63 + int i, n; 64 + 65 + if (header->length < sizeof(struct acpi_table_mcfg)) 66 + return -EINVAL; 67 + 68 + n = (header->length - sizeof(struct acpi_table_mcfg)) / 69 + sizeof(struct acpi_mcfg_allocation); 70 + mcfg = (struct acpi_table_mcfg *)header; 71 + mptr = (struct acpi_mcfg_allocation *) &mcfg[1]; 72 + 73 + for (i = 0; i < n; i++, mptr++) { 74 + msi_group[i].pci_segment = mptr->pci_segment; 75 + pch_group[i].node = msi_group[i].node = (mptr->address >> 44) & 0xf; 76 + } 77 + 78 + return 0; 79 + } 80 + 81 + static void __init init_vec_parent_group(void) 82 + { 83 + int i; 84 + 85 + for (i = 0; i < MAX_IO_PICS; i++) { 86 + msi_group[i].pci_segment = -1; 87 + msi_group[i].node = -1; 88 + pch_group[i].node = -1; 89 + } 90 + 91 + acpi_table_parse(ACPI_SIG_MCFG, early_pci_mcfg_parse); 92 + } 93 + 94 + static int __init get_ipi_irq(void) 95 + { 96 + struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY); 97 + 98 + if (d) 99 + return irq_create_mapping(d, EXCCODE_IPI - EXCCODE_INT_START); 100 + 101 + return -EINVAL; 102 + } 103 + 55 104 void __init init_IRQ(void) 56 105 { 57 106 int i; ··· 110 69 clear_csr_ecfg(ECFG0_IM); 111 70 clear_csr_estat(ESTATF_IP); 112 71 72 + init_vec_parent_group(); 113 73 irqchip_init(); 114 74 #ifdef CONFIG_SMP 115 - ipi_irq = EXCCODE_IPI - EXCCODE_INT_START; 75 + ipi_irq = get_ipi_irq(); 76 + if (ipi_irq < 0) 77 + panic("IPI IRQ mapping failed\n"); 116 78 irq_set_percpu_devid(ipi_irq); 117 79 r = request_percpu_irq(ipi_irq, loongson3_ipi_interrupt, "IPI", &ipi_dummy_dev); 118 80 if (r < 0)
+13 -1
arch/loongarch/kernel/time.c
··· 123 123 csr_write64(-init_timeval, LOONGARCH_CSR_CNTC); 124 124 } 125 125 126 + static int get_timer_irq(void) 127 + { 128 + struct irq_domain *d = irq_find_matching_fwnode(cpuintc_handle, DOMAIN_BUS_ANY); 129 + 130 + if (d) 131 + return irq_create_mapping(d, EXCCODE_TIMER - EXCCODE_INT_START); 132 + 133 + return -EINVAL; 134 + } 135 + 126 136 int constant_clockevent_init(void) 127 137 { 128 138 unsigned int irq; ··· 142 132 struct clock_event_device *cd; 143 133 static int timer_irq_installed = 0; 144 134 145 - irq = EXCCODE_TIMER - EXCCODE_INT_START; 135 + irq = get_timer_irq(); 136 + if (irq < 0) 137 + pr_err("Failed to map irq %d (timer)\n", irq); 146 138 147 139 cd = &per_cpu(constant_clockevent_device, cpu); 148 140
+2 -2
arch/mips/cavium-octeon/octeon-irq.c
··· 263 263 264 264 #ifdef CONFIG_SMP 265 265 int cpu; 266 - struct cpumask *mask = irq_data_get_affinity_mask(data); 266 + const struct cpumask *mask = irq_data_get_affinity_mask(data); 267 267 int weight = cpumask_weight(mask); 268 268 struct octeon_ciu_chip_data *cd = irq_data_get_irq_chip_data(data); 269 269 ··· 758 758 { 759 759 int cpu = smp_processor_id(); 760 760 cpumask_t new_affinity; 761 - struct cpumask *mask = irq_data_get_affinity_mask(data); 761 + const struct cpumask *mask = irq_data_get_affinity_mask(data); 762 762 763 763 if (!cpumask_test_cpu(cpu, mask)) 764 764 return;
+2 -1
arch/mips/include/asm/mach-loongson64/irq.h
··· 7 7 #define NR_MIPS_CPU_IRQS 8 8 8 #define NR_MAX_CHAINED_IRQS 40 /* Chained IRQs means those not directly used by devices */ 9 9 #define NR_IRQS (NR_IRQS_LEGACY + NR_MIPS_CPU_IRQS + NR_MAX_CHAINED_IRQS + 256) 10 - 10 + #define MAX_IO_PICS 1 11 11 #define MIPS_CPU_IRQ_BASE NR_IRQS_LEGACY 12 + #define GSI_MIN_CPU_IRQ 0 12 13 13 14 #include <asm/mach-generic/irq.h> 14 15
+1 -1
arch/parisc/kernel/irq.c
··· 315 315 { 316 316 #ifdef CONFIG_SMP 317 317 struct irq_data *d = irq_get_irq_data(irq); 318 - cpumask_copy(irq_data_get_affinity_mask(d), cpumask_of(cpu)); 318 + irq_data_update_affinity(d, cpumask_of(cpu)); 319 319 #endif 320 320 321 321 return per_cpu(cpu_data, cpu).txn_addr;
+4 -3
arch/sh/kernel/irq.c
··· 230 230 struct irq_data *data = irq_get_irq_data(irq); 231 231 232 232 if (irq_data_get_node(data) == cpu) { 233 - struct cpumask *mask = irq_data_get_affinity_mask(data); 233 + const struct cpumask *mask = irq_data_get_affinity_mask(data); 234 234 unsigned int newcpu = cpumask_any_and(mask, 235 235 cpu_online_mask); 236 236 if (newcpu >= nr_cpu_ids) { 237 237 pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n", 238 238 irq, cpu); 239 239 240 - cpumask_setall(mask); 240 + irq_set_affinity(irq, cpu_all_mask); 241 + } else { 242 + irq_set_affinity(irq, mask); 241 243 } 242 - irq_set_affinity(irq, mask); 243 244 } 244 245 } 245 246 }
+1 -1
arch/x86/hyperv/irqdomain.c
··· 192 192 struct pci_dev *dev; 193 193 struct hv_interrupt_entry out_entry, *stored_entry; 194 194 struct irq_cfg *cfg = irqd_cfg(data); 195 - cpumask_t *affinity; 195 + const cpumask_t *affinity; 196 196 int cpu; 197 197 u64 status; 198 198
+4 -3
arch/xtensa/kernel/irq.c
··· 169 169 170 170 for_each_active_irq(i) { 171 171 struct irq_data *data = irq_get_irq_data(i); 172 - struct cpumask *mask; 172 + const struct cpumask *mask; 173 173 unsigned int newcpu; 174 174 175 175 if (irqd_is_per_cpu(data)) ··· 185 185 pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n", 186 186 i, cpu); 187 187 188 - cpumask_setall(mask); 188 + irq_set_affinity(i, cpu_all_mask); 189 + } else { 190 + irq_set_affinity(i, mask); 189 191 } 190 - irq_set_affinity(i, mask); 191 192 } 192 193 } 193 194 #endif /* CONFIG_HOTPLUG_CPU */
+3
drivers/acpi/bus.c
··· 1144 1144 case ACPI_IRQ_MODEL_PLATFORM: 1145 1145 message = "platform specific model"; 1146 1146 break; 1147 + case ACPI_IRQ_MODEL_LPIC: 1148 + message = "LPIC"; 1149 + break; 1147 1150 default: 1148 1151 pr_info("Unknown interrupt routing model\n"); 1149 1152 return -ENODEV;
+41 -17
drivers/acpi/irq.c
··· 12 12 13 13 enum acpi_irq_model_id acpi_irq_model; 14 14 15 - static struct fwnode_handle *acpi_gsi_domain_id; 15 + static struct fwnode_handle *(*acpi_get_gsi_domain_id)(u32 gsi); 16 + static u32 (*acpi_gsi_to_irq_fallback)(u32 gsi); 16 17 17 18 /** 18 19 * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI ··· 27 26 */ 28 27 int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) 29 28 { 30 - struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id, 31 - DOMAIN_BUS_ANY); 29 + struct irq_domain *d; 32 30 31 + d = irq_find_matching_fwnode(acpi_get_gsi_domain_id(gsi), 32 + DOMAIN_BUS_ANY); 33 33 *irq = irq_find_mapping(d, gsi); 34 34 /* 35 - * *irq == 0 means no mapping, that should 36 - * be reported as a failure 35 + * *irq == 0 means no mapping, that should be reported as a 36 + * failure, unless there is an arch-specific fallback handler. 37 37 */ 38 + if (!*irq && acpi_gsi_to_irq_fallback) 39 + *irq = acpi_gsi_to_irq_fallback(gsi); 40 + 38 41 return (*irq > 0) ? 0 : -EINVAL; 39 42 } 40 43 EXPORT_SYMBOL_GPL(acpi_gsi_to_irq); ··· 58 53 { 59 54 struct irq_fwspec fwspec; 60 55 61 - if (WARN_ON(!acpi_gsi_domain_id)) { 56 + fwspec.fwnode = acpi_get_gsi_domain_id(gsi); 57 + if (WARN_ON(!fwspec.fwnode)) { 62 58 pr_warn("GSI: No registered irqchip, giving up\n"); 63 59 return -EINVAL; 64 60 } 65 61 66 - fwspec.fwnode = acpi_gsi_domain_id; 67 62 fwspec.param[0] = gsi; 68 63 fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity); 69 64 fwspec.param_count = 2; ··· 78 73 */ 79 74 void acpi_unregister_gsi(u32 gsi) 80 75 { 81 - struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id, 82 - DOMAIN_BUS_ANY); 76 + struct irq_domain *d; 83 77 int irq; 84 78 85 79 if (WARN_ON(acpi_irq_model == ACPI_IRQ_MODEL_GIC && gsi < 16)) 86 80 return; 87 81 82 + d = irq_find_matching_fwnode(acpi_get_gsi_domain_id(gsi), 83 + DOMAIN_BUS_ANY); 88 84 irq = irq_find_mapping(d, gsi); 89 85 irq_dispose_mapping(irq); 90 86 } ··· 103 97 * The referenced device fwhandle or NULL on failure 104 98 */ 105 99 static struct fwnode_handle * 106 - acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source) 100 + acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source, 101 + u32 gsi) 107 102 { 108 103 struct fwnode_handle *result; 109 104 struct acpi_device *device; ··· 112 105 acpi_status status; 113 106 114 107 if (!source->string_length) 115 - return acpi_gsi_domain_id; 108 + return acpi_get_gsi_domain_id(gsi); 116 109 117 110 status = acpi_get_handle(NULL, source->string_ptr, &handle); 118 111 if (WARN_ON(ACPI_FAILURE(status))) ··· 201 194 ctx->index -= irq->interrupt_count; 202 195 return AE_OK; 203 196 } 204 - fwnode = acpi_gsi_domain_id; 197 + fwnode = acpi_get_gsi_domain_id(irq->interrupts[ctx->index]); 205 198 acpi_irq_parse_one_match(fwnode, irq->interrupts[ctx->index], 206 199 irq->triggering, irq->polarity, 207 200 irq->shareable, ctx); ··· 214 207 ctx->index -= eirq->interrupt_count; 215 208 return AE_OK; 216 209 } 217 - fwnode = acpi_get_irq_source_fwhandle(&eirq->resource_source); 210 + fwnode = acpi_get_irq_source_fwhandle(&eirq->resource_source, 211 + eirq->interrupts[ctx->index]); 218 212 acpi_irq_parse_one_match(fwnode, eirq->interrupts[ctx->index], 219 213 eirq->triggering, eirq->polarity, 220 214 eirq->shareable, ctx); ··· 299 291 * GSI interrupts 300 292 */ 301 293 void __init acpi_set_irq_model(enum acpi_irq_model_id model, 302 - struct fwnode_handle *fwnode) 294 + struct fwnode_handle *(*fn)(u32)) 303 295 { 304 296 acpi_irq_model = model; 305 - acpi_gsi_domain_id = fwnode; 297 + acpi_get_gsi_domain_id = fn; 298 + } 299 + 300 + /** 301 + * acpi_set_gsi_to_irq_fallback - Register a GSI transfer 302 + * callback to fallback to arch specified implementation. 303 + * @fn: arch-specific fallback handler 304 + */ 305 + void __init acpi_set_gsi_to_irq_fallback(u32 (*fn)(u32)) 306 + { 307 + acpi_gsi_to_irq_fallback = fn; 306 308 } 307 309 308 310 /** ··· 330 312 const struct irq_domain_ops *ops, 331 313 void *host_data) 332 314 { 333 - struct irq_domain *d = irq_find_matching_fwnode(acpi_gsi_domain_id, 334 - DOMAIN_BUS_ANY); 315 + struct irq_domain *d; 316 + 317 + /* This only works for the GIC model... */ 318 + if (acpi_irq_model != ACPI_IRQ_MODEL_GIC) 319 + return NULL; 320 + 321 + d = irq_find_matching_fwnode(acpi_get_gsi_domain_id(0), 322 + DOMAIN_BUS_ANY); 335 323 336 324 if (!d) 337 325 return NULL;
+6 -9
drivers/gpio/gpio-msc313.c
··· 550 550 * so we need to provide the fwspec. Essentially gpiochip_populate_parent_fwspec_twocell 551 551 * that puts GIC_SPI into the first cell. 552 552 */ 553 - static void *msc313_gpio_populate_parent_fwspec(struct gpio_chip *gc, 554 - unsigned int parent_hwirq, 555 - unsigned int parent_type) 553 + static int msc313_gpio_populate_parent_fwspec(struct gpio_chip *gc, 554 + union gpio_irq_fwspec *gfwspec, 555 + unsigned int parent_hwirq, 556 + unsigned int parent_type) 556 557 { 557 - struct irq_fwspec *fwspec; 558 - 559 - fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); 560 - if (!fwspec) 561 - return NULL; 558 + struct irq_fwspec *fwspec = &gfwspec->fwspec; 562 559 563 560 fwspec->fwnode = gc->irq.parent_domain->fwnode; 564 561 fwspec->param_count = 3; ··· 563 566 fwspec->param[1] = parent_hwirq; 564 567 fwspec->param[2] = parent_type; 565 568 566 - return fwspec; 569 + return 0; 567 570 } 568 571 569 572 static int msc313e_gpio_child_to_parent_hwirq(struct gpio_chip *chip,
+6 -9
drivers/gpio/gpio-tegra.c
··· 443 443 return 0; 444 444 } 445 445 446 - static void *tegra_gpio_populate_parent_fwspec(struct gpio_chip *chip, 447 - unsigned int parent_hwirq, 448 - unsigned int parent_type) 446 + static int tegra_gpio_populate_parent_fwspec(struct gpio_chip *chip, 447 + union gpio_irq_fwspec *gfwspec, 448 + unsigned int parent_hwirq, 449 + unsigned int parent_type) 449 450 { 450 - struct irq_fwspec *fwspec; 451 - 452 - fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); 453 - if (!fwspec) 454 - return NULL; 451 + struct irq_fwspec *fwspec = &gfwspec->fwspec; 455 452 456 453 fwspec->fwnode = chip->irq.parent_domain->fwnode; 457 454 fwspec->param_count = 3; ··· 456 459 fwspec->param[1] = parent_hwirq; 457 460 fwspec->param[2] = parent_type; 458 461 459 - return fwspec; 462 + return 0; 460 463 } 461 464 462 465 #ifdef CONFIG_PM_SLEEP
+6 -9
drivers/gpio/gpio-tegra186.c
··· 621 621 return 0; 622 622 } 623 623 624 - static void *tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, 625 - unsigned int parent_hwirq, 626 - unsigned int parent_type) 624 + static int tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, 625 + union gpio_irq_fwspec *gfwspec, 626 + unsigned int parent_hwirq, 627 + unsigned int parent_type) 627 628 { 628 629 struct tegra_gpio *gpio = gpiochip_get_data(chip); 629 - struct irq_fwspec *fwspec; 630 - 631 - fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); 632 - if (!fwspec) 633 - return NULL; 630 + struct irq_fwspec *fwspec = &gfwspec->fwspec; 634 631 635 632 fwspec->fwnode = chip->irq.parent_domain->fwnode; 636 633 fwspec->param_count = 3; ··· 635 638 fwspec->param[1] = parent_hwirq; 636 639 fwspec->param[2] = parent_type; 637 640 638 - return fwspec; 641 + return 0; 639 642 } 640 643 641 644 static int tegra186_gpio_child_to_parent_hwirq(struct gpio_chip *chip,
+6 -11
drivers/gpio/gpio-thunderx.c
··· 15 15 #include <linux/module.h> 16 16 #include <linux/pci.h> 17 17 #include <linux/spinlock.h> 18 - #include <asm-generic/msi.h> 19 - 20 18 21 19 #define GPIO_RX_DAT 0x0 22 20 #define GPIO_TX_SET 0x8 ··· 406 408 return 0; 407 409 } 408 410 409 - static void *thunderx_gpio_populate_parent_alloc_info(struct gpio_chip *chip, 410 - unsigned int parent_hwirq, 411 - unsigned int parent_type) 411 + static int thunderx_gpio_populate_parent_alloc_info(struct gpio_chip *chip, 412 + union gpio_irq_fwspec *gfwspec, 413 + unsigned int parent_hwirq, 414 + unsigned int parent_type) 412 415 { 413 - msi_alloc_info_t *info; 414 - 415 - info = kmalloc(sizeof(*info), GFP_KERNEL); 416 - if (!info) 417 - return NULL; 416 + msi_alloc_info_t *info = &gfwspec->msiinfo; 418 417 419 418 info->hwirq = parent_hwirq; 420 - return info; 419 + return 0; 421 420 } 422 421 423 422 static int thunderx_gpio_probe(struct pci_dev *pdev,
+6 -9
drivers/gpio/gpio-visconti.c
··· 103 103 return -EINVAL; 104 104 } 105 105 106 - static void *visconti_gpio_populate_parent_fwspec(struct gpio_chip *chip, 107 - unsigned int parent_hwirq, 108 - unsigned int parent_type) 106 + static int visconti_gpio_populate_parent_fwspec(struct gpio_chip *chip, 107 + union gpio_irq_fwspec *gfwspec, 108 + unsigned int parent_hwirq, 109 + unsigned int parent_type) 109 110 { 110 - struct irq_fwspec *fwspec; 111 - 112 - fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); 113 - if (!fwspec) 114 - return NULL; 111 + struct irq_fwspec *fwspec = &gfwspec->fwspec; 115 112 116 113 fwspec->fwnode = chip->irq.parent_domain->fwnode; 117 114 fwspec->param_count = 3; ··· 116 119 fwspec->param[1] = parent_hwirq; 117 120 fwspec->param[2] = parent_type; 118 121 119 - return fwspec; 122 + return 0; 120 123 } 121 124 122 125 static int visconti_gpio_probe(struct platform_device *pdev)
+24 -27
drivers/gpio/gpiolib.c
··· 1107 1107 irq_hw_number_t hwirq; 1108 1108 unsigned int type = IRQ_TYPE_NONE; 1109 1109 struct irq_fwspec *fwspec = data; 1110 - void *parent_arg; 1110 + union gpio_irq_fwspec gpio_parent_fwspec = {}; 1111 1111 unsigned int parent_hwirq; 1112 1112 unsigned int parent_type; 1113 1113 struct gpio_irq_chip *girq = &gc->irq; ··· 1147 1147 irq_set_probe(irq); 1148 1148 1149 1149 /* This parent only handles asserted level IRQs */ 1150 - parent_arg = girq->populate_parent_alloc_arg(gc, parent_hwirq, parent_type); 1151 - if (!parent_arg) 1152 - return -ENOMEM; 1150 + ret = girq->populate_parent_alloc_arg(gc, &gpio_parent_fwspec, 1151 + parent_hwirq, parent_type); 1152 + if (ret) 1153 + return ret; 1153 1154 1154 1155 chip_dbg(gc, "alloc_irqs_parent for %d parent hwirq %d\n", 1155 1156 irq, parent_hwirq); 1156 1157 irq_set_lockdep_class(irq, gc->irq.lock_key, gc->irq.request_key); 1157 - ret = irq_domain_alloc_irqs_parent(d, irq, 1, parent_arg); 1158 + ret = irq_domain_alloc_irqs_parent(d, irq, 1, &gpio_parent_fwspec); 1158 1159 /* 1159 1160 * If the parent irqdomain is msi, the interrupts have already 1160 1161 * been allocated, so the EEXIST is good. ··· 1167 1166 "failed to allocate parent hwirq %d for hwirq %lu\n", 1168 1167 parent_hwirq, hwirq); 1169 1168 1170 - kfree(parent_arg); 1171 1169 return ret; 1172 1170 } 1173 1171 ··· 1181 1181 ops->activate = gpiochip_irq_domain_activate; 1182 1182 ops->deactivate = gpiochip_irq_domain_deactivate; 1183 1183 ops->alloc = gpiochip_hierarchy_irq_domain_alloc; 1184 - ops->free = irq_domain_free_irqs_common; 1185 1184 1186 1185 /* 1187 - * We only allow overriding the translate() function for 1186 + * We only allow overriding the translate() and free() functions for 1188 1187 * hierarchical chips, and this should only be done if the user 1189 - * really need something other than 1:1 translation. 1188 + * really need something other than 1:1 translation for translate() 1189 + * callback and free if user wants to free up any resources which 1190 + * were allocated during callbacks, for example populate_parent_alloc_arg. 1190 1191 */ 1191 1192 if (!ops->translate) 1192 1193 ops->translate = gpiochip_hierarchy_irq_domain_translate; 1194 + if (!ops->free) 1195 + ops->free = irq_domain_free_irqs_common; 1193 1196 } 1194 1197 1195 1198 static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) ··· 1233 1230 return !!gc->irq.parent_domain; 1234 1231 } 1235 1232 1236 - void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, 1237 - unsigned int parent_hwirq, 1238 - unsigned int parent_type) 1233 + int gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, 1234 + union gpio_irq_fwspec *gfwspec, 1235 + unsigned int parent_hwirq, 1236 + unsigned int parent_type) 1239 1237 { 1240 - struct irq_fwspec *fwspec; 1241 - 1242 - fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); 1243 - if (!fwspec) 1244 - return NULL; 1238 + struct irq_fwspec *fwspec = &gfwspec->fwspec; 1245 1239 1246 1240 fwspec->fwnode = gc->irq.parent_domain->fwnode; 1247 1241 fwspec->param_count = 2; 1248 1242 fwspec->param[0] = parent_hwirq; 1249 1243 fwspec->param[1] = parent_type; 1250 1244 1251 - return fwspec; 1245 + return 0; 1252 1246 } 1253 1247 EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell); 1254 1248 1255 - void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, 1256 - unsigned int parent_hwirq, 1257 - unsigned int parent_type) 1249 + int gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, 1250 + union gpio_irq_fwspec *gfwspec, 1251 + unsigned int parent_hwirq, 1252 + unsigned int parent_type) 1258 1253 { 1259 - struct irq_fwspec *fwspec; 1260 - 1261 - fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); 1262 - if (!fwspec) 1263 - return NULL; 1254 + struct irq_fwspec *fwspec = &gfwspec->fwspec; 1264 1255 1265 1256 fwspec->fwnode = gc->irq.parent_domain->fwnode; 1266 1257 fwspec->param_count = 4; ··· 1263 1266 fwspec->param[2] = 0; 1264 1267 fwspec->param[3] = parent_type; 1265 1268 1266 - return fwspec; 1269 + return 0; 1267 1270 } 1268 1271 EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell); 1269 1272
+1 -1
drivers/iommu/hyperv-iommu.c
··· 194 194 u32 vector; 195 195 struct irq_cfg *cfg; 196 196 int ioapic_id; 197 - struct cpumask *affinity; 197 + const struct cpumask *affinity; 198 198 int cpu; 199 199 struct hv_interrupt_entry entry; 200 200 struct hyperv_root_ir_data *data = irq_data->chip_data;
+49 -11
drivers/irqchip/Kconfig
··· 8 8 config ARM_GIC 9 9 bool 10 10 select IRQ_DOMAIN_HIERARCHY 11 - select GENERIC_IRQ_EFFECTIVE_AFF_MASK 11 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 12 12 13 13 config ARM_GIC_PM 14 14 bool ··· 34 34 bool 35 35 select IRQ_DOMAIN_HIERARCHY 36 36 select PARTITION_PERCPU 37 - select GENERIC_IRQ_EFFECTIVE_AFF_MASK 37 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 38 38 39 39 config ARM_GIC_V3_ITS 40 40 bool ··· 76 76 bool 77 77 select GENERIC_IRQ_CHIP 78 78 select PCI_MSI if PCI 79 - select GENERIC_IRQ_EFFECTIVE_AFF_MASK 79 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 80 80 81 81 config ALPINE_MSI 82 82 bool ··· 112 112 bool 113 113 select GENERIC_IRQ_CHIP 114 114 select IRQ_DOMAIN 115 - select GENERIC_IRQ_EFFECTIVE_AFF_MASK 115 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 116 116 117 117 config BCM7038_L1_IRQ 118 118 tristate "Broadcom STB 7038-style L1/L2 interrupt controller driver" ··· 120 120 default ARCH_BRCMSTB || BMIPS_GENERIC 121 121 select GENERIC_IRQ_CHIP 122 122 select IRQ_DOMAIN 123 - select GENERIC_IRQ_EFFECTIVE_AFF_MASK 123 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 124 124 125 125 config BCM7120_L2_IRQ 126 126 tristate "Broadcom STB 7120-style L2 interrupt controller driver" ··· 177 177 config IRQ_MIPS_CPU 178 178 bool 179 179 select GENERIC_IRQ_CHIP 180 - select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING 180 + select GENERIC_IRQ_IPI if SMP && SYS_SUPPORTS_MULTITHREADING 181 181 select IRQ_DOMAIN 182 - select GENERIC_IRQ_EFFECTIVE_AFF_MASK 182 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 183 183 184 184 config CLPS711X_IRQCHIP 185 185 bool ··· 242 242 Enable support for the Renesas RZ/A1 Interrupt Controller, to use up 243 243 to 8 external interrupts with configurable sense select. 244 244 245 + config RENESAS_RZG2L_IRQC 246 + bool "Renesas RZ/G2L (and alike SoC) IRQC support" if COMPILE_TEST 247 + select GENERIC_IRQ_CHIP 248 + select IRQ_DOMAIN_HIERARCHY 249 + help 250 + Enable support for the Renesas RZ/G2L (and alike SoC) Interrupt Controller 251 + for external devices. 252 + 245 253 config SL28CPLD_INTC 246 254 bool "Kontron sl28cpld IRQ controller" 247 255 depends on MFD_SL28CPLD=y || COMPILE_TEST ··· 302 294 config XTENSA_MX 303 295 bool 304 296 select IRQ_DOMAIN 305 - select GENERIC_IRQ_EFFECTIVE_AFF_MASK 297 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 306 298 307 299 config XILINX_INTC 308 300 bool "Xilinx Interrupt Controller IP" ··· 330 322 331 323 config MIPS_GIC 332 324 bool 333 - select GENERIC_IRQ_IPI 325 + select GENERIC_IRQ_IPI if SMP 326 + select IRQ_DOMAIN_HIERARCHY 334 327 select MIPS_CM 335 328 336 329 config INGENIC_IRQ ··· 539 530 bool "SiFive Platform-Level Interrupt Controller" 540 531 depends on RISCV 541 532 select IRQ_DOMAIN_HIERARCHY 533 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK if SMP 542 534 help 543 535 This enables support for the PLIC chip found in SiFive (and 544 536 potentially other) RISC-V systems. The PLIC controls devices ··· 556 546 Say yes here to add support for the IRQ combiner devices embedded 557 547 in Samsung Exynos chips. 558 548 549 + config IRQ_LOONGARCH_CPU 550 + bool 551 + select GENERIC_IRQ_CHIP 552 + select IRQ_DOMAIN 553 + select GENERIC_IRQ_EFFECTIVE_AFF_MASK 554 + help 555 + Support for the LoongArch CPU Interrupt Controller. For details of 556 + irq chip hierarchy on LoongArch platforms please read the document 557 + Documentation/loongarch/irq-chip-model.rst. 558 + 559 559 config LOONGSON_LIOINTC 560 560 bool "Loongson Local I/O Interrupt Controller" 561 561 depends on MACH_LOONGSON64 ··· 574 554 select GENERIC_IRQ_CHIP 575 555 help 576 556 Support for the Loongson Local I/O Interrupt Controller. 557 + 558 + config LOONGSON_EIOINTC 559 + bool "Loongson Extend I/O Interrupt Controller" 560 + depends on LOONGARCH 561 + depends on MACH_LOONGSON64 562 + default MACH_LOONGSON64 563 + select IRQ_DOMAIN_HIERARCHY 564 + select GENERIC_IRQ_CHIP 565 + help 566 + Support for the Loongson3 Extend I/O Interrupt Vector Controller. 577 567 578 568 config LOONGSON_HTPIC 579 569 bool "Loongson3 HyperTransport PIC Controller" ··· 604 574 605 575 config LOONGSON_PCH_PIC 606 576 bool "Loongson PCH PIC Controller" 607 - depends on MACH_LOONGSON64 || COMPILE_TEST 577 + depends on MACH_LOONGSON64 608 578 default MACH_LOONGSON64 609 579 select IRQ_DOMAIN_HIERARCHY 610 580 select IRQ_FASTEOI_HIERARCHY_HANDLERS ··· 613 583 614 584 config LOONGSON_PCH_MSI 615 585 bool "Loongson PCH MSI Controller" 616 - depends on MACH_LOONGSON64 || COMPILE_TEST 586 + depends on MACH_LOONGSON64 617 587 depends on PCI 618 588 default MACH_LOONGSON64 619 589 select IRQ_DOMAIN_HIERARCHY 620 590 select PCI_MSI 621 591 help 622 592 Support for the Loongson PCH MSI Controller. 593 + 594 + config LOONGSON_PCH_LPC 595 + bool "Loongson PCH LPC Controller" 596 + depends on MACH_LOONGSON64 597 + default (MACH_LOONGSON64 && LOONGARCH) 598 + select IRQ_DOMAIN_HIERARCHY 599 + help 600 + Support for the Loongson PCH LPC Controller. 623 601 624 602 config MST_IRQ 625 603 bool "MStar Interrupt Controller"
+4
drivers/irqchip/Makefile
··· 51 51 obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o 52 52 obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o 53 53 obj-$(CONFIG_RENESAS_RZA1_IRQC) += irq-renesas-rza1.o 54 + obj-$(CONFIG_RENESAS_RZG2L_IRQC) += irq-renesas-rzg2l.o 54 55 obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o 55 56 obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o 56 57 obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o ··· 104 103 obj-$(CONFIG_TI_SCI_INTR_IRQCHIP) += irq-ti-sci-intr.o 105 104 obj-$(CONFIG_TI_SCI_INTA_IRQCHIP) += irq-ti-sci-inta.o 106 105 obj-$(CONFIG_TI_PRUSS_INTC) += irq-pruss-intc.o 106 + obj-$(CONFIG_IRQ_LOONGARCH_CPU) += irq-loongarch-cpu.o 107 107 obj-$(CONFIG_LOONGSON_LIOINTC) += irq-loongson-liointc.o 108 + obj-$(CONFIG_LOONGSON_EIOINTC) += irq-loongson-eiointc.o 108 109 obj-$(CONFIG_LOONGSON_HTPIC) += irq-loongson-htpic.o 109 110 obj-$(CONFIG_LOONGSON_HTVEC) += irq-loongson-htvec.o 110 111 obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-loongson-pch-pic.o 111 112 obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o 113 + obj-$(CONFIG_LOONGSON_PCH_LPC) += irq-loongson-pch-lpc.o 112 114 obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o 113 115 obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o 114 116 obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o
+2 -2
drivers/irqchip/irq-bcm6345-l1.c
··· 216 216 enabled = intc->cpus[old_cpu]->enable_cache[word] & mask; 217 217 if (enabled) 218 218 __bcm6345_l1_mask(d); 219 - cpumask_copy(irq_data_get_affinity_mask(d), dest); 219 + irq_data_update_affinity(d, dest); 220 220 if (enabled) 221 221 __bcm6345_l1_unmask(d); 222 222 } else { 223 - cpumask_copy(irq_data_get_affinity_mask(d), dest); 223 + irq_data_update_affinity(d, dest); 224 224 } 225 225 raw_spin_unlock_irqrestore(&intc->lock, flags); 226 226
+13 -7
drivers/irqchip/irq-gic-v3.c
··· 1783 1783 * the security state of the GIC (controlled by the GICD_CTRL.DS bit) 1784 1784 * and if Group 0 interrupts can be delivered to Linux in the non-secure 1785 1785 * world as FIQs (controlled by the SCR_EL3.FIQ bit). These affect the 1786 - * the ICC_PMR_EL1 register and the priority that software assigns to 1786 + * ICC_PMR_EL1 register and the priority that software assigns to 1787 1787 * interrupts: 1788 1788 * 1789 1789 * GICD_CTRL.DS | SCR_EL3.FIQ | ICC_PMR_EL1 | Group 1 priority ··· 2381 2381 vgic_set_kvm_info(&gic_v3_kvm_info); 2382 2382 } 2383 2383 2384 + static struct fwnode_handle *gsi_domain_handle; 2385 + 2386 + static struct fwnode_handle *gic_v3_get_gsi_domain_id(u32 gsi) 2387 + { 2388 + return gsi_domain_handle; 2389 + } 2390 + 2384 2391 static int __init 2385 2392 gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end) 2386 2393 { 2387 2394 struct acpi_madt_generic_distributor *dist; 2388 - struct fwnode_handle *domain_handle; 2389 2395 size_t size; 2390 2396 int i, err; 2391 2397 ··· 2423 2417 if (err) 2424 2418 goto out_redist_unmap; 2425 2419 2426 - domain_handle = irq_domain_alloc_fwnode(&dist->base_address); 2427 - if (!domain_handle) { 2420 + gsi_domain_handle = irq_domain_alloc_fwnode(&dist->base_address); 2421 + if (!gsi_domain_handle) { 2428 2422 err = -ENOMEM; 2429 2423 goto out_redist_unmap; 2430 2424 } 2431 2425 2432 2426 err = gic_init_bases(acpi_data.dist_base, acpi_data.redist_regs, 2433 - acpi_data.nr_redist_regions, 0, domain_handle); 2427 + acpi_data.nr_redist_regions, 0, gsi_domain_handle); 2434 2428 if (err) 2435 2429 goto out_fwhandle_free; 2436 2430 2437 - acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle); 2431 + acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v3_get_gsi_domain_id); 2438 2432 2439 2433 if (static_branch_likely(&supports_deactivate_key)) 2440 2434 gic_acpi_setup_kvm_info(); ··· 2442 2436 return 0; 2443 2437 2444 2438 out_fwhandle_free: 2445 - irq_domain_free_fwnode(domain_handle); 2439 + irq_domain_free_fwnode(gsi_domain_handle); 2446 2440 out_redist_unmap: 2447 2441 for (i = 0; i < acpi_data.nr_redist_regions; i++) 2448 2442 if (acpi_data.redist_regs[i].redist_base)
+12 -6
drivers/irqchip/irq-gic.c
··· 1682 1682 vgic_set_kvm_info(&gic_v2_kvm_info); 1683 1683 } 1684 1684 1685 + static struct fwnode_handle *gsi_domain_handle; 1686 + 1687 + static struct fwnode_handle *gic_v2_get_gsi_domain_id(u32 gsi) 1688 + { 1689 + return gsi_domain_handle; 1690 + } 1691 + 1685 1692 static int __init gic_v2_acpi_init(union acpi_subtable_headers *header, 1686 1693 const unsigned long end) 1687 1694 { 1688 1695 struct acpi_madt_generic_distributor *dist; 1689 - struct fwnode_handle *domain_handle; 1690 1696 struct gic_chip_data *gic = &gic_data[0]; 1691 1697 int count, ret; 1692 1698 ··· 1730 1724 /* 1731 1725 * Initialize GIC instance zero (no multi-GIC support). 1732 1726 */ 1733 - domain_handle = irq_domain_alloc_fwnode(&dist->base_address); 1734 - if (!domain_handle) { 1727 + gsi_domain_handle = irq_domain_alloc_fwnode(&dist->base_address); 1728 + if (!gsi_domain_handle) { 1735 1729 pr_err("Unable to allocate domain handle\n"); 1736 1730 gic_teardown(gic); 1737 1731 return -ENOMEM; 1738 1732 } 1739 1733 1740 - ret = __gic_init_bases(gic, domain_handle); 1734 + ret = __gic_init_bases(gic, gsi_domain_handle); 1741 1735 if (ret) { 1742 1736 pr_err("Failed to initialise GIC\n"); 1743 - irq_domain_free_fwnode(domain_handle); 1737 + irq_domain_free_fwnode(gsi_domain_handle); 1744 1738 gic_teardown(gic); 1745 1739 return ret; 1746 1740 } 1747 1741 1748 - acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle); 1742 + acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v2_get_gsi_domain_id); 1749 1743 1750 1744 if (IS_ENABLED(CONFIG_ARM_GIC_V2M)) 1751 1745 gicv2m_init(NULL, gic_data[0].domain);
+148
drivers/irqchip/irq-loongarch-cpu.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 + */ 5 + 6 + #include <linux/init.h> 7 + #include <linux/kernel.h> 8 + #include <linux/interrupt.h> 9 + #include <linux/irq.h> 10 + #include <linux/irqchip.h> 11 + #include <linux/irqdomain.h> 12 + 13 + #include <asm/loongarch.h> 14 + #include <asm/setup.h> 15 + 16 + static struct irq_domain *irq_domain; 17 + struct fwnode_handle *cpuintc_handle; 18 + 19 + static u32 lpic_gsi_to_irq(u32 gsi) 20 + { 21 + /* Only pch irqdomain transferring is required for LoongArch. */ 22 + if (gsi >= GSI_MIN_PCH_IRQ && gsi <= GSI_MAX_PCH_IRQ) 23 + return acpi_register_gsi(NULL, gsi, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_HIGH); 24 + 25 + return 0; 26 + } 27 + 28 + static struct fwnode_handle *lpic_get_gsi_domain_id(u32 gsi) 29 + { 30 + int id; 31 + struct fwnode_handle *domain_handle = NULL; 32 + 33 + switch (gsi) { 34 + case GSI_MIN_CPU_IRQ ... GSI_MAX_CPU_IRQ: 35 + if (liointc_handle) 36 + domain_handle = liointc_handle; 37 + break; 38 + 39 + case GSI_MIN_LPC_IRQ ... GSI_MAX_LPC_IRQ: 40 + if (pch_lpc_handle) 41 + domain_handle = pch_lpc_handle; 42 + break; 43 + 44 + case GSI_MIN_PCH_IRQ ... GSI_MAX_PCH_IRQ: 45 + id = find_pch_pic(gsi); 46 + if (id >= 0 && pch_pic_handle[id]) 47 + domain_handle = pch_pic_handle[id]; 48 + break; 49 + } 50 + 51 + return domain_handle; 52 + } 53 + 54 + static void mask_loongarch_irq(struct irq_data *d) 55 + { 56 + clear_csr_ecfg(ECFGF(d->hwirq)); 57 + } 58 + 59 + static void unmask_loongarch_irq(struct irq_data *d) 60 + { 61 + set_csr_ecfg(ECFGF(d->hwirq)); 62 + } 63 + 64 + static struct irq_chip cpu_irq_controller = { 65 + .name = "CPUINTC", 66 + .irq_mask = mask_loongarch_irq, 67 + .irq_unmask = unmask_loongarch_irq, 68 + }; 69 + 70 + static void handle_cpu_irq(struct pt_regs *regs) 71 + { 72 + int hwirq; 73 + unsigned int estat = read_csr_estat() & CSR_ESTAT_IS; 74 + 75 + while ((hwirq = ffs(estat))) { 76 + estat &= ~BIT(hwirq - 1); 77 + generic_handle_domain_irq(irq_domain, hwirq - 1); 78 + } 79 + } 80 + 81 + static int loongarch_cpu_intc_map(struct irq_domain *d, unsigned int irq, 82 + irq_hw_number_t hwirq) 83 + { 84 + irq_set_noprobe(irq); 85 + irq_set_chip_and_handler(irq, &cpu_irq_controller, handle_percpu_irq); 86 + 87 + return 0; 88 + } 89 + 90 + static const struct irq_domain_ops loongarch_cpu_intc_irq_domain_ops = { 91 + .map = loongarch_cpu_intc_map, 92 + .xlate = irq_domain_xlate_onecell, 93 + }; 94 + 95 + static int __init 96 + liointc_parse_madt(union acpi_subtable_headers *header, 97 + const unsigned long end) 98 + { 99 + struct acpi_madt_lio_pic *liointc_entry = (struct acpi_madt_lio_pic *)header; 100 + 101 + return liointc_acpi_init(irq_domain, liointc_entry); 102 + } 103 + 104 + static int __init 105 + eiointc_parse_madt(union acpi_subtable_headers *header, 106 + const unsigned long end) 107 + { 108 + struct acpi_madt_eio_pic *eiointc_entry = (struct acpi_madt_eio_pic *)header; 109 + 110 + return eiointc_acpi_init(irq_domain, eiointc_entry); 111 + } 112 + 113 + static int __init acpi_cascade_irqdomain_init(void) 114 + { 115 + acpi_table_parse_madt(ACPI_MADT_TYPE_LIO_PIC, 116 + liointc_parse_madt, 0); 117 + acpi_table_parse_madt(ACPI_MADT_TYPE_EIO_PIC, 118 + eiointc_parse_madt, 0); 119 + return 0; 120 + } 121 + 122 + static int __init cpuintc_acpi_init(union acpi_subtable_headers *header, 123 + const unsigned long end) 124 + { 125 + if (irq_domain) 126 + return 0; 127 + 128 + /* Mask interrupts. */ 129 + clear_csr_ecfg(ECFG0_IM); 130 + clear_csr_estat(ESTATF_IP); 131 + 132 + cpuintc_handle = irq_domain_alloc_fwnode(NULL); 133 + irq_domain = irq_domain_create_linear(cpuintc_handle, EXCCODE_INT_NUM, 134 + &loongarch_cpu_intc_irq_domain_ops, NULL); 135 + 136 + if (!irq_domain) 137 + panic("Failed to add irqdomain for LoongArch CPU"); 138 + 139 + set_handle_irq(&handle_cpu_irq); 140 + acpi_set_irq_model(ACPI_IRQ_MODEL_LPIC, lpic_get_gsi_domain_id); 141 + acpi_set_gsi_to_irq_fallback(lpic_gsi_to_irq); 142 + acpi_cascade_irqdomain_init(); 143 + 144 + return 0; 145 + } 146 + 147 + IRQCHIP_ACPI_DECLARE(cpuintc_v1, ACPI_MADT_TYPE_CORE_PIC, 148 + NULL, ACPI_MADT_CORE_PIC_VERSION_V1, cpuintc_acpi_init);
+395
drivers/irqchip/irq-loongson-eiointc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Loongson Extend I/O Interrupt Controller support 4 + * 5 + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 6 + */ 7 + 8 + #define pr_fmt(fmt) "eiointc: " fmt 9 + 10 + #include <linux/interrupt.h> 11 + #include <linux/irq.h> 12 + #include <linux/irqchip.h> 13 + #include <linux/irqdomain.h> 14 + #include <linux/irqchip/chained_irq.h> 15 + #include <linux/kernel.h> 16 + #include <linux/platform_device.h> 17 + #include <linux/of_address.h> 18 + #include <linux/of_irq.h> 19 + #include <linux/of_platform.h> 20 + 21 + #define EIOINTC_REG_NODEMAP 0x14a0 22 + #define EIOINTC_REG_IPMAP 0x14c0 23 + #define EIOINTC_REG_ENABLE 0x1600 24 + #define EIOINTC_REG_BOUNCE 0x1680 25 + #define EIOINTC_REG_ISR 0x1800 26 + #define EIOINTC_REG_ROUTE 0x1c00 27 + 28 + #define VEC_REG_COUNT 4 29 + #define VEC_COUNT_PER_REG 64 30 + #define VEC_COUNT (VEC_REG_COUNT * VEC_COUNT_PER_REG) 31 + #define VEC_REG_IDX(irq_id) ((irq_id) / VEC_COUNT_PER_REG) 32 + #define VEC_REG_BIT(irq_id) ((irq_id) % VEC_COUNT_PER_REG) 33 + #define EIOINTC_ALL_ENABLE 0xffffffff 34 + 35 + #define MAX_EIO_NODES (NR_CPUS / CORES_PER_EIO_NODE) 36 + 37 + static int nr_pics; 38 + 39 + struct eiointc_priv { 40 + u32 node; 41 + nodemask_t node_map; 42 + cpumask_t cpuspan_map; 43 + struct fwnode_handle *domain_handle; 44 + struct irq_domain *eiointc_domain; 45 + }; 46 + 47 + static struct eiointc_priv *eiointc_priv[MAX_IO_PICS]; 48 + 49 + static void eiointc_enable(void) 50 + { 51 + uint64_t misc; 52 + 53 + misc = iocsr_read64(LOONGARCH_IOCSR_MISC_FUNC); 54 + misc |= IOCSR_MISC_FUNC_EXT_IOI_EN; 55 + iocsr_write64(misc, LOONGARCH_IOCSR_MISC_FUNC); 56 + } 57 + 58 + static int cpu_to_eio_node(int cpu) 59 + { 60 + return cpu_logical_map(cpu) / CORES_PER_EIO_NODE; 61 + } 62 + 63 + static void eiointc_set_irq_route(int pos, unsigned int cpu, unsigned int mnode, nodemask_t *node_map) 64 + { 65 + int i, node, cpu_node, route_node; 66 + unsigned char coremap; 67 + uint32_t pos_off, data, data_byte, data_mask; 68 + 69 + pos_off = pos & ~3; 70 + data_byte = pos & 3; 71 + data_mask = ~BIT_MASK(data_byte) & 0xf; 72 + 73 + /* Calculate node and coremap of target irq */ 74 + cpu_node = cpu_logical_map(cpu) / CORES_PER_EIO_NODE; 75 + coremap = BIT(cpu_logical_map(cpu) % CORES_PER_EIO_NODE); 76 + 77 + for_each_online_cpu(i) { 78 + node = cpu_to_eio_node(i); 79 + if (!node_isset(node, *node_map)) 80 + continue; 81 + 82 + /* EIO node 0 is in charge of inter-node interrupt dispatch */ 83 + route_node = (node == mnode) ? cpu_node : node; 84 + data = ((coremap | (route_node << 4)) << (data_byte * 8)); 85 + csr_any_send(EIOINTC_REG_ROUTE + pos_off, data, data_mask, node * CORES_PER_EIO_NODE); 86 + } 87 + } 88 + 89 + static DEFINE_RAW_SPINLOCK(affinity_lock); 90 + 91 + static int eiointc_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity, bool force) 92 + { 93 + unsigned int cpu; 94 + unsigned long flags; 95 + uint32_t vector, regaddr; 96 + struct cpumask intersect_affinity; 97 + struct eiointc_priv *priv = d->domain->host_data; 98 + 99 + raw_spin_lock_irqsave(&affinity_lock, flags); 100 + 101 + cpumask_and(&intersect_affinity, affinity, cpu_online_mask); 102 + cpumask_and(&intersect_affinity, &intersect_affinity, &priv->cpuspan_map); 103 + 104 + if (cpumask_empty(&intersect_affinity)) { 105 + raw_spin_unlock_irqrestore(&affinity_lock, flags); 106 + return -EINVAL; 107 + } 108 + cpu = cpumask_first(&intersect_affinity); 109 + 110 + vector = d->hwirq; 111 + regaddr = EIOINTC_REG_ENABLE + ((vector >> 5) << 2); 112 + 113 + /* Mask target vector */ 114 + csr_any_send(regaddr, EIOINTC_ALL_ENABLE & (~BIT(vector & 0x1F)), 0x0, 0); 115 + /* Set route for target vector */ 116 + eiointc_set_irq_route(vector, cpu, priv->node, &priv->node_map); 117 + /* Unmask target vector */ 118 + csr_any_send(regaddr, EIOINTC_ALL_ENABLE, 0x0, 0); 119 + 120 + irq_data_update_effective_affinity(d, cpumask_of(cpu)); 121 + 122 + raw_spin_unlock_irqrestore(&affinity_lock, flags); 123 + 124 + return IRQ_SET_MASK_OK; 125 + } 126 + 127 + static int eiointc_index(int node) 128 + { 129 + int i; 130 + 131 + for (i = 0; i < nr_pics; i++) { 132 + if (node_isset(node, eiointc_priv[i]->node_map)) 133 + return i; 134 + } 135 + 136 + return -1; 137 + } 138 + 139 + static int eiointc_router_init(unsigned int cpu) 140 + { 141 + int i, bit; 142 + uint32_t data; 143 + uint32_t node = cpu_to_eio_node(cpu); 144 + uint32_t index = eiointc_index(node); 145 + 146 + if (index < 0) { 147 + pr_err("Error: invalid nodemap!\n"); 148 + return -1; 149 + } 150 + 151 + if ((cpu_logical_map(cpu) % CORES_PER_EIO_NODE) == 0) { 152 + eiointc_enable(); 153 + 154 + for (i = 0; i < VEC_COUNT / 32; i++) { 155 + data = (((1 << (i * 2 + 1)) << 16) | (1 << (i * 2))); 156 + iocsr_write32(data, EIOINTC_REG_NODEMAP + i * 4); 157 + } 158 + 159 + for (i = 0; i < VEC_COUNT / 32 / 4; i++) { 160 + bit = BIT(1 + index); /* Route to IP[1 + index] */ 161 + data = bit | (bit << 8) | (bit << 16) | (bit << 24); 162 + iocsr_write32(data, EIOINTC_REG_IPMAP + i * 4); 163 + } 164 + 165 + for (i = 0; i < VEC_COUNT / 4; i++) { 166 + /* Route to Node-0 Core-0 */ 167 + if (index == 0) 168 + bit = BIT(cpu_logical_map(0)); 169 + else 170 + bit = (eiointc_priv[index]->node << 4) | 1; 171 + 172 + data = bit | (bit << 8) | (bit << 16) | (bit << 24); 173 + iocsr_write32(data, EIOINTC_REG_ROUTE + i * 4); 174 + } 175 + 176 + for (i = 0; i < VEC_COUNT / 32; i++) { 177 + data = 0xffffffff; 178 + iocsr_write32(data, EIOINTC_REG_ENABLE + i * 4); 179 + iocsr_write32(data, EIOINTC_REG_BOUNCE + i * 4); 180 + } 181 + } 182 + 183 + return 0; 184 + } 185 + 186 + static void eiointc_irq_dispatch(struct irq_desc *desc) 187 + { 188 + int i; 189 + u64 pending; 190 + bool handled = false; 191 + struct irq_chip *chip = irq_desc_get_chip(desc); 192 + struct eiointc_priv *priv = irq_desc_get_handler_data(desc); 193 + 194 + chained_irq_enter(chip, desc); 195 + 196 + for (i = 0; i < VEC_REG_COUNT; i++) { 197 + pending = iocsr_read64(EIOINTC_REG_ISR + (i << 3)); 198 + iocsr_write64(pending, EIOINTC_REG_ISR + (i << 3)); 199 + while (pending) { 200 + int bit = __ffs(pending); 201 + int irq = bit + VEC_COUNT_PER_REG * i; 202 + 203 + generic_handle_domain_irq(priv->eiointc_domain, irq); 204 + pending &= ~BIT(bit); 205 + handled = true; 206 + } 207 + } 208 + 209 + if (!handled) 210 + spurious_interrupt(); 211 + 212 + chained_irq_exit(chip, desc); 213 + } 214 + 215 + static void eiointc_ack_irq(struct irq_data *d) 216 + { 217 + } 218 + 219 + static void eiointc_mask_irq(struct irq_data *d) 220 + { 221 + } 222 + 223 + static void eiointc_unmask_irq(struct irq_data *d) 224 + { 225 + } 226 + 227 + static struct irq_chip eiointc_irq_chip = { 228 + .name = "EIOINTC", 229 + .irq_ack = eiointc_ack_irq, 230 + .irq_mask = eiointc_mask_irq, 231 + .irq_unmask = eiointc_unmask_irq, 232 + .irq_set_affinity = eiointc_set_irq_affinity, 233 + }; 234 + 235 + static int eiointc_domain_alloc(struct irq_domain *domain, unsigned int virq, 236 + unsigned int nr_irqs, void *arg) 237 + { 238 + int ret; 239 + unsigned int i, type; 240 + unsigned long hwirq = 0; 241 + struct eiointc *priv = domain->host_data; 242 + 243 + ret = irq_domain_translate_onecell(domain, arg, &hwirq, &type); 244 + if (ret) 245 + return ret; 246 + 247 + for (i = 0; i < nr_irqs; i++) { 248 + irq_domain_set_info(domain, virq + i, hwirq + i, &eiointc_irq_chip, 249 + priv, handle_edge_irq, NULL, NULL); 250 + } 251 + 252 + return 0; 253 + } 254 + 255 + static void eiointc_domain_free(struct irq_domain *domain, unsigned int virq, 256 + unsigned int nr_irqs) 257 + { 258 + int i; 259 + 260 + for (i = 0; i < nr_irqs; i++) { 261 + struct irq_data *d = irq_domain_get_irq_data(domain, virq + i); 262 + 263 + irq_set_handler(virq + i, NULL); 264 + irq_domain_reset_irq_data(d); 265 + } 266 + } 267 + 268 + static const struct irq_domain_ops eiointc_domain_ops = { 269 + .translate = irq_domain_translate_onecell, 270 + .alloc = eiointc_domain_alloc, 271 + .free = eiointc_domain_free, 272 + }; 273 + 274 + static void acpi_set_vec_parent(int node, struct irq_domain *parent, struct acpi_vector_group *vec_group) 275 + { 276 + int i; 277 + 278 + if (cpu_has_flatmode) 279 + node = cpu_to_node(node * CORES_PER_EIO_NODE); 280 + 281 + for (i = 0; i < MAX_IO_PICS; i++) { 282 + if (node == vec_group[i].node) { 283 + vec_group[i].parent = parent; 284 + return; 285 + } 286 + } 287 + } 288 + 289 + struct irq_domain *acpi_get_vec_parent(int node, struct acpi_vector_group *vec_group) 290 + { 291 + int i; 292 + 293 + for (i = 0; i < MAX_IO_PICS; i++) { 294 + if (node == vec_group[i].node) 295 + return vec_group[i].parent; 296 + } 297 + return NULL; 298 + } 299 + 300 + static int __init 301 + pch_pic_parse_madt(union acpi_subtable_headers *header, 302 + const unsigned long end) 303 + { 304 + struct acpi_madt_bio_pic *pchpic_entry = (struct acpi_madt_bio_pic *)header; 305 + unsigned int node = (pchpic_entry->address >> 44) & 0xf; 306 + struct irq_domain *parent = acpi_get_vec_parent(node, pch_group); 307 + 308 + if (parent) 309 + return pch_pic_acpi_init(parent, pchpic_entry); 310 + 311 + return -EINVAL; 312 + } 313 + 314 + static int __init 315 + pch_msi_parse_madt(union acpi_subtable_headers *header, 316 + const unsigned long end) 317 + { 318 + struct acpi_madt_msi_pic *pchmsi_entry = (struct acpi_madt_msi_pic *)header; 319 + struct irq_domain *parent = acpi_get_vec_parent(eiointc_priv[nr_pics - 1]->node, msi_group); 320 + 321 + if (parent) 322 + return pch_msi_acpi_init(parent, pchmsi_entry); 323 + 324 + return -EINVAL; 325 + } 326 + 327 + static int __init acpi_cascade_irqdomain_init(void) 328 + { 329 + acpi_table_parse_madt(ACPI_MADT_TYPE_BIO_PIC, 330 + pch_pic_parse_madt, 0); 331 + acpi_table_parse_madt(ACPI_MADT_TYPE_MSI_PIC, 332 + pch_msi_parse_madt, 1); 333 + return 0; 334 + } 335 + 336 + int __init eiointc_acpi_init(struct irq_domain *parent, 337 + struct acpi_madt_eio_pic *acpi_eiointc) 338 + { 339 + int i, parent_irq; 340 + unsigned long node_map; 341 + struct eiointc_priv *priv; 342 + 343 + priv = kzalloc(sizeof(*priv), GFP_KERNEL); 344 + if (!priv) 345 + return -ENOMEM; 346 + 347 + priv->domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_eiointc); 348 + if (!priv->domain_handle) { 349 + pr_err("Unable to allocate domain handle\n"); 350 + goto out_free_priv; 351 + } 352 + 353 + priv->node = acpi_eiointc->node; 354 + node_map = acpi_eiointc->node_map ? : -1ULL; 355 + 356 + for_each_possible_cpu(i) { 357 + if (node_map & (1ULL << cpu_to_eio_node(i))) { 358 + node_set(cpu_to_eio_node(i), priv->node_map); 359 + cpumask_or(&priv->cpuspan_map, &priv->cpuspan_map, cpumask_of(i)); 360 + } 361 + } 362 + 363 + /* Setup IRQ domain */ 364 + priv->eiointc_domain = irq_domain_create_linear(priv->domain_handle, VEC_COUNT, 365 + &eiointc_domain_ops, priv); 366 + if (!priv->eiointc_domain) { 367 + pr_err("loongson-eiointc: cannot add IRQ domain\n"); 368 + goto out_free_handle; 369 + } 370 + 371 + eiointc_priv[nr_pics++] = priv; 372 + 373 + eiointc_router_init(0); 374 + 375 + parent_irq = irq_create_mapping(parent, acpi_eiointc->cascade); 376 + irq_set_chained_handler_and_data(parent_irq, eiointc_irq_dispatch, priv); 377 + 378 + cpuhp_setup_state_nocalls(CPUHP_AP_IRQ_LOONGARCH_STARTING, 379 + "irqchip/loongarch/intc:starting", 380 + eiointc_router_init, NULL); 381 + 382 + acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, pch_group); 383 + acpi_set_vec_parent(acpi_eiointc->node, priv->eiointc_domain, msi_group); 384 + acpi_cascade_irqdomain_init(); 385 + 386 + return 0; 387 + 388 + out_free_handle: 389 + irq_domain_free_fwnode(priv->domain_handle); 390 + priv->domain_handle = NULL; 391 + out_free_priv: 392 + kfree(priv); 393 + 394 + return -ENOMEM; 395 + }
+130 -77
drivers/irqchip/irq-loongson-liointc.c
··· 23 23 #endif 24 24 25 25 #define LIOINTC_CHIP_IRQ 32 26 - #define LIOINTC_NUM_PARENT 4 26 + #define LIOINTC_NUM_PARENT 4 27 27 #define LIOINTC_NUM_CORES 4 28 28 29 29 #define LIOINTC_INTC_CHIP_START 0x20 ··· 57 57 u8 map_cache[LIOINTC_CHIP_IRQ]; 58 58 bool has_lpc_irq_errata; 59 59 }; 60 + 61 + struct fwnode_handle *liointc_handle; 60 62 61 63 static void liointc_chained_handle_irq(struct irq_desc *desc) 62 64 { ··· 155 153 irq_gc_unlock_irqrestore(gc, flags); 156 154 } 157 155 158 - static const char * const parent_names[] = {"int0", "int1", "int2", "int3"}; 159 - static const char * const core_reg_names[] = {"isr0", "isr1", "isr2", "isr3"}; 156 + static int parent_irq[LIOINTC_NUM_PARENT]; 157 + static u32 parent_int_map[LIOINTC_NUM_PARENT]; 158 + static const char *const parent_names[] = {"int0", "int1", "int2", "int3"}; 159 + static const char *const core_reg_names[] = {"isr0", "isr1", "isr2", "isr3"}; 160 160 161 - static void __iomem *liointc_get_reg_byname(struct device_node *node, 162 - const char *name) 161 + static int liointc_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, 162 + const u32 *intspec, unsigned int intsize, 163 + unsigned long *out_hwirq, unsigned int *out_type) 163 164 { 164 - int index = of_property_match_string(node, "reg-names", name); 165 - 166 - if (index < 0) 167 - return NULL; 168 - 169 - return of_iomap(node, index); 165 + if (WARN_ON(intsize < 1)) 166 + return -EINVAL; 167 + *out_hwirq = intspec[0] - GSI_MIN_CPU_IRQ; 168 + *out_type = IRQ_TYPE_NONE; 169 + return 0; 170 170 } 171 171 172 - static int __init liointc_of_init(struct device_node *node, 173 - struct device_node *parent) 172 + static const struct irq_domain_ops acpi_irq_gc_ops = { 173 + .map = irq_map_generic_chip, 174 + .unmap = irq_unmap_generic_chip, 175 + .xlate = liointc_domain_xlate, 176 + }; 177 + 178 + static int liointc_init(phys_addr_t addr, unsigned long size, int revision, 179 + struct fwnode_handle *domain_handle, struct device_node *node) 174 180 { 181 + int i, err; 182 + void __iomem *base; 183 + struct irq_chip_type *ct; 175 184 struct irq_chip_generic *gc; 176 185 struct irq_domain *domain; 177 - struct irq_chip_type *ct; 178 186 struct liointc_priv *priv; 179 - void __iomem *base; 180 - u32 of_parent_int_map[LIOINTC_NUM_PARENT]; 181 - int parent_irq[LIOINTC_NUM_PARENT]; 182 - bool have_parent = FALSE; 183 - int sz, i, err = 0; 184 187 185 188 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 186 189 if (!priv) 187 190 return -ENOMEM; 188 191 189 - if (of_device_is_compatible(node, "loongson,liointc-2.0")) { 190 - base = liointc_get_reg_byname(node, "main"); 191 - if (!base) { 192 - err = -ENODEV; 193 - goto out_free_priv; 194 - } 192 + base = ioremap(addr, size); 193 + if (!base) 194 + goto out_free_priv; 195 195 196 - for (i = 0; i < LIOINTC_NUM_CORES; i++) 197 - priv->core_isr[i] = liointc_get_reg_byname(node, core_reg_names[i]); 198 - if (!priv->core_isr[0]) { 199 - err = -ENODEV; 200 - goto out_iounmap_base; 201 - } 202 - } else { 203 - base = of_iomap(node, 0); 204 - if (!base) { 205 - err = -ENODEV; 206 - goto out_free_priv; 207 - } 208 - 209 - for (i = 0; i < LIOINTC_NUM_CORES; i++) 210 - priv->core_isr[i] = base + LIOINTC_REG_INTC_STATUS; 211 - } 212 - 213 - for (i = 0; i < LIOINTC_NUM_PARENT; i++) { 214 - parent_irq[i] = of_irq_get_byname(node, parent_names[i]); 215 - if (parent_irq[i] > 0) 216 - have_parent = TRUE; 217 - } 218 - if (!have_parent) { 219 - err = -ENODEV; 220 - goto out_iounmap_isr; 221 - } 222 - 223 - sz = of_property_read_variable_u32_array(node, 224 - "loongson,parent_int_map", 225 - &of_parent_int_map[0], 226 - LIOINTC_NUM_PARENT, 227 - LIOINTC_NUM_PARENT); 228 - if (sz < 4) { 229 - pr_err("loongson-liointc: No parent_int_map\n"); 230 - err = -ENODEV; 231 - goto out_iounmap_isr; 232 - } 196 + for (i = 0; i < LIOINTC_NUM_CORES; i++) 197 + priv->core_isr[i] = base + LIOINTC_REG_INTC_STATUS; 233 198 234 199 for (i = 0; i < LIOINTC_NUM_PARENT; i++) 235 - priv->handler[i].parent_int_map = of_parent_int_map[i]; 200 + priv->handler[i].parent_int_map = parent_int_map[i]; 201 + 202 + if (revision > 1) { 203 + for (i = 0; i < LIOINTC_NUM_CORES; i++) { 204 + int index = of_property_match_string(node, 205 + "reg-names", core_reg_names[i]); 206 + 207 + if (index < 0) 208 + return -EINVAL; 209 + 210 + priv->core_isr[i] = of_iomap(node, index); 211 + } 212 + } 236 213 237 214 /* Setup IRQ domain */ 238 - domain = irq_domain_add_linear(node, 32, 215 + if (!acpi_disabled) 216 + domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ, 217 + &acpi_irq_gc_ops, priv); 218 + else 219 + domain = irq_domain_create_linear(domain_handle, LIOINTC_CHIP_IRQ, 239 220 &irq_generic_chip_ops, priv); 240 221 if (!domain) { 241 222 pr_err("loongson-liointc: cannot add IRQ domain\n"); 242 - err = -EINVAL; 243 - goto out_iounmap_isr; 223 + goto out_iounmap; 244 224 } 245 225 246 - err = irq_alloc_domain_generic_chips(domain, 32, 1, 247 - node->full_name, handle_level_irq, 248 - IRQ_NOPROBE, 0, 0); 226 + err = irq_alloc_domain_generic_chips(domain, LIOINTC_CHIP_IRQ, 1, 227 + (node ? node->full_name : "LIOINTC"), 228 + handle_level_irq, 0, IRQ_NOPROBE, 0); 249 229 if (err) { 250 230 pr_err("loongson-liointc: unable to register IRQ domain\n"); 251 231 goto out_free_domain; ··· 283 299 liointc_chained_handle_irq, &priv->handler[i]); 284 300 } 285 301 302 + liointc_handle = domain_handle; 286 303 return 0; 287 304 288 305 out_free_domain: 289 306 irq_domain_remove(domain); 290 - out_iounmap_isr: 291 - for (i = 0; i < LIOINTC_NUM_CORES; i++) { 292 - if (!priv->core_isr[i]) 293 - continue; 294 - iounmap(priv->core_isr[i]); 295 - } 296 - out_iounmap_base: 307 + out_iounmap: 297 308 iounmap(base); 298 309 out_free_priv: 299 310 kfree(priv); 300 311 301 - return err; 312 + return -EINVAL; 313 + } 314 + 315 + #ifdef CONFIG_OF 316 + 317 + static int __init liointc_of_init(struct device_node *node, 318 + struct device_node *parent) 319 + { 320 + bool have_parent = FALSE; 321 + int sz, i, index, revision, err = 0; 322 + struct resource res; 323 + 324 + if (!of_device_is_compatible(node, "loongson,liointc-2.0")) { 325 + index = 0; 326 + revision = 1; 327 + } else { 328 + index = of_property_match_string(node, "reg-names", "main"); 329 + revision = 2; 330 + } 331 + 332 + if (of_address_to_resource(node, index, &res)) 333 + return -EINVAL; 334 + 335 + for (i = 0; i < LIOINTC_NUM_PARENT; i++) { 336 + parent_irq[i] = of_irq_get_byname(node, parent_names[i]); 337 + if (parent_irq[i] > 0) 338 + have_parent = TRUE; 339 + } 340 + if (!have_parent) 341 + return -ENODEV; 342 + 343 + sz = of_property_read_variable_u32_array(node, 344 + "loongson,parent_int_map", 345 + &parent_int_map[0], 346 + LIOINTC_NUM_PARENT, 347 + LIOINTC_NUM_PARENT); 348 + if (sz < 4) { 349 + pr_err("loongson-liointc: No parent_int_map\n"); 350 + return -ENODEV; 351 + } 352 + 353 + err = liointc_init(res.start, resource_size(&res), 354 + revision, of_node_to_fwnode(node), node); 355 + if (err < 0) 356 + return err; 357 + 358 + return 0; 302 359 } 303 360 304 361 IRQCHIP_DECLARE(loongson_liointc_1_0, "loongson,liointc-1.0", liointc_of_init); 305 362 IRQCHIP_DECLARE(loongson_liointc_1_0a, "loongson,liointc-1.0a", liointc_of_init); 306 363 IRQCHIP_DECLARE(loongson_liointc_2_0, "loongson,liointc-2.0", liointc_of_init); 364 + 365 + #endif 366 + 367 + #ifdef CONFIG_ACPI 368 + int __init liointc_acpi_init(struct irq_domain *parent, struct acpi_madt_lio_pic *acpi_liointc) 369 + { 370 + int ret; 371 + struct fwnode_handle *domain_handle; 372 + 373 + parent_int_map[0] = acpi_liointc->cascade_map[0]; 374 + parent_int_map[1] = acpi_liointc->cascade_map[1]; 375 + 376 + parent_irq[0] = irq_create_mapping(parent, acpi_liointc->cascade[0]); 377 + parent_irq[1] = irq_create_mapping(parent, acpi_liointc->cascade[1]); 378 + 379 + domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_liointc); 380 + if (!domain_handle) { 381 + pr_err("Unable to allocate domain handle\n"); 382 + return -ENOMEM; 383 + } 384 + ret = liointc_init(acpi_liointc->address, acpi_liointc->size, 385 + 1, domain_handle, NULL); 386 + if (ret) 387 + irq_domain_free_fwnode(domain_handle); 388 + 389 + return ret; 390 + } 391 + #endif
+205
drivers/irqchip/irq-loongson-pch-lpc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Loongson LPC Interrupt Controller support 4 + * 5 + * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 6 + */ 7 + 8 + #define pr_fmt(fmt) "lpc: " fmt 9 + 10 + #include <linux/interrupt.h> 11 + #include <linux/irq.h> 12 + #include <linux/irqchip.h> 13 + #include <linux/irqchip/chained_irq.h> 14 + #include <linux/irqdomain.h> 15 + #include <linux/kernel.h> 16 + 17 + /* Registers */ 18 + #define LPC_INT_CTL 0x00 19 + #define LPC_INT_ENA 0x04 20 + #define LPC_INT_STS 0x08 21 + #define LPC_INT_CLR 0x0c 22 + #define LPC_INT_POL 0x10 23 + #define LPC_COUNT 16 24 + 25 + /* LPC_INT_CTL */ 26 + #define LPC_INT_CTL_EN BIT(31) 27 + 28 + struct pch_lpc { 29 + void __iomem *base; 30 + struct irq_domain *lpc_domain; 31 + raw_spinlock_t lpc_lock; 32 + u32 saved_reg_ctl; 33 + u32 saved_reg_ena; 34 + u32 saved_reg_pol; 35 + }; 36 + 37 + struct fwnode_handle *pch_lpc_handle; 38 + 39 + static void lpc_irq_ack(struct irq_data *d) 40 + { 41 + unsigned long flags; 42 + struct pch_lpc *priv = d->domain->host_data; 43 + 44 + raw_spin_lock_irqsave(&priv->lpc_lock, flags); 45 + writel(0x1 << d->hwirq, priv->base + LPC_INT_CLR); 46 + raw_spin_unlock_irqrestore(&priv->lpc_lock, flags); 47 + } 48 + 49 + static void lpc_irq_mask(struct irq_data *d) 50 + { 51 + unsigned long flags; 52 + struct pch_lpc *priv = d->domain->host_data; 53 + 54 + raw_spin_lock_irqsave(&priv->lpc_lock, flags); 55 + writel(readl(priv->base + LPC_INT_ENA) & (~(0x1 << (d->hwirq))), 56 + priv->base + LPC_INT_ENA); 57 + raw_spin_unlock_irqrestore(&priv->lpc_lock, flags); 58 + } 59 + 60 + static void lpc_irq_unmask(struct irq_data *d) 61 + { 62 + unsigned long flags; 63 + struct pch_lpc *priv = d->domain->host_data; 64 + 65 + raw_spin_lock_irqsave(&priv->lpc_lock, flags); 66 + writel(readl(priv->base + LPC_INT_ENA) | (0x1 << (d->hwirq)), 67 + priv->base + LPC_INT_ENA); 68 + raw_spin_unlock_irqrestore(&priv->lpc_lock, flags); 69 + } 70 + 71 + static int lpc_irq_set_type(struct irq_data *d, unsigned int type) 72 + { 73 + u32 val; 74 + u32 mask = 0x1 << (d->hwirq); 75 + struct pch_lpc *priv = d->domain->host_data; 76 + 77 + if (!(type & IRQ_TYPE_LEVEL_MASK)) 78 + return 0; 79 + 80 + val = readl(priv->base + LPC_INT_POL); 81 + 82 + if (type == IRQ_TYPE_LEVEL_HIGH) 83 + val |= mask; 84 + else 85 + val &= ~mask; 86 + 87 + writel(val, priv->base + LPC_INT_POL); 88 + 89 + return 0; 90 + } 91 + 92 + static const struct irq_chip pch_lpc_irq_chip = { 93 + .name = "PCH LPC", 94 + .irq_mask = lpc_irq_mask, 95 + .irq_unmask = lpc_irq_unmask, 96 + .irq_ack = lpc_irq_ack, 97 + .irq_set_type = lpc_irq_set_type, 98 + .flags = IRQCHIP_SKIP_SET_WAKE, 99 + }; 100 + 101 + static void lpc_irq_dispatch(struct irq_desc *desc) 102 + { 103 + u32 pending, bit; 104 + struct irq_chip *chip = irq_desc_get_chip(desc); 105 + struct pch_lpc *priv = irq_desc_get_handler_data(desc); 106 + 107 + chained_irq_enter(chip, desc); 108 + 109 + pending = readl(priv->base + LPC_INT_ENA); 110 + pending &= readl(priv->base + LPC_INT_STS); 111 + if (!pending) 112 + spurious_interrupt(); 113 + 114 + while (pending) { 115 + bit = __ffs(pending); 116 + 117 + generic_handle_domain_irq(priv->lpc_domain, bit); 118 + pending &= ~BIT(bit); 119 + } 120 + chained_irq_exit(chip, desc); 121 + } 122 + 123 + static int pch_lpc_map(struct irq_domain *d, unsigned int irq, 124 + irq_hw_number_t hw) 125 + { 126 + irq_set_chip_and_handler(irq, &pch_lpc_irq_chip, handle_level_irq); 127 + return 0; 128 + } 129 + 130 + static const struct irq_domain_ops pch_lpc_domain_ops = { 131 + .map = pch_lpc_map, 132 + .translate = irq_domain_translate_twocell, 133 + }; 134 + 135 + static void pch_lpc_reset(struct pch_lpc *priv) 136 + { 137 + /* Enable the LPC interrupt, bit31: en bit30: edge */ 138 + writel(LPC_INT_CTL_EN, priv->base + LPC_INT_CTL); 139 + writel(0, priv->base + LPC_INT_ENA); 140 + /* Clear all 18-bit interrpt bit */ 141 + writel(GENMASK(17, 0), priv->base + LPC_INT_CLR); 142 + } 143 + 144 + static int pch_lpc_disabled(struct pch_lpc *priv) 145 + { 146 + return (readl(priv->base + LPC_INT_ENA) == 0xffffffff) && 147 + (readl(priv->base + LPC_INT_STS) == 0xffffffff); 148 + } 149 + 150 + int __init pch_lpc_acpi_init(struct irq_domain *parent, 151 + struct acpi_madt_lpc_pic *acpi_pchlpc) 152 + { 153 + int parent_irq; 154 + struct pch_lpc *priv; 155 + struct irq_fwspec fwspec; 156 + struct fwnode_handle *irq_handle; 157 + 158 + priv = kzalloc(sizeof(*priv), GFP_KERNEL); 159 + if (!priv) 160 + return -ENOMEM; 161 + 162 + raw_spin_lock_init(&priv->lpc_lock); 163 + 164 + priv->base = ioremap(acpi_pchlpc->address, acpi_pchlpc->size); 165 + if (!priv->base) 166 + goto free_priv; 167 + 168 + if (pch_lpc_disabled(priv)) { 169 + pr_err("Failed to get LPC status\n"); 170 + goto iounmap_base; 171 + } 172 + 173 + irq_handle = irq_domain_alloc_named_fwnode("lpcintc"); 174 + if (!irq_handle) { 175 + pr_err("Unable to allocate domain handle\n"); 176 + goto iounmap_base; 177 + } 178 + 179 + priv->lpc_domain = irq_domain_create_linear(irq_handle, LPC_COUNT, 180 + &pch_lpc_domain_ops, priv); 181 + if (!priv->lpc_domain) { 182 + pr_err("Failed to create IRQ domain\n"); 183 + goto free_irq_handle; 184 + } 185 + pch_lpc_reset(priv); 186 + 187 + fwspec.fwnode = parent->fwnode; 188 + fwspec.param[0] = acpi_pchlpc->cascade + GSI_MIN_PCH_IRQ; 189 + fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; 190 + fwspec.param_count = 2; 191 + parent_irq = irq_create_fwspec_mapping(&fwspec); 192 + irq_set_chained_handler_and_data(parent_irq, lpc_irq_dispatch, priv); 193 + 194 + pch_lpc_handle = irq_handle; 195 + return 0; 196 + 197 + free_irq_handle: 198 + irq_domain_free_fwnode(irq_handle); 199 + iounmap_base: 200 + iounmap(priv->base); 201 + free_priv: 202 + kfree(priv); 203 + 204 + return -ENOMEM; 205 + }
+85 -42
drivers/irqchip/irq-loongson-pch-msi.c
··· 15 15 #include <linux/pci.h> 16 16 #include <linux/slab.h> 17 17 18 + static int nr_pics; 19 + 18 20 struct pch_msi_data { 19 21 struct mutex msi_map_lock; 20 22 phys_addr_t doorbell; ··· 24 22 u32 num_irqs; /* The number of vectors for MSIs */ 25 23 unsigned long *msi_map; 26 24 }; 25 + 26 + static struct fwnode_handle *pch_msi_handle[MAX_IO_PICS]; 27 27 28 28 static void pch_msi_mask_msi_irq(struct irq_data *d) 29 29 { ··· 158 154 }; 159 155 160 156 static int pch_msi_init_domains(struct pch_msi_data *priv, 161 - struct device_node *node, 162 - struct irq_domain *parent) 157 + struct irq_domain *parent, 158 + struct fwnode_handle *domain_handle) 163 159 { 164 160 struct irq_domain *middle_domain, *msi_domain; 165 161 166 - middle_domain = irq_domain_create_linear(of_node_to_fwnode(node), 162 + middle_domain = irq_domain_create_linear(domain_handle, 167 163 priv->num_irqs, 168 164 &pch_msi_middle_domain_ops, 169 165 priv); ··· 175 171 middle_domain->parent = parent; 176 172 irq_domain_update_bus_token(middle_domain, DOMAIN_BUS_NEXUS); 177 173 178 - msi_domain = pci_msi_create_irq_domain(of_node_to_fwnode(node), 174 + msi_domain = pci_msi_create_irq_domain(domain_handle, 179 175 &pch_msi_domain_info, 180 176 middle_domain); 181 177 if (!msi_domain) { ··· 187 183 return 0; 188 184 } 189 185 190 - static int pch_msi_init(struct device_node *node, 191 - struct device_node *parent) 186 + static int pch_msi_init(phys_addr_t msg_address, int irq_base, int irq_count, 187 + struct irq_domain *parent_domain, struct fwnode_handle *domain_handle) 192 188 { 193 - struct pch_msi_data *priv; 194 - struct irq_domain *parent_domain; 195 - struct resource res; 196 189 int ret; 197 - 198 - parent_domain = irq_find_host(parent); 199 - if (!parent_domain) { 200 - pr_err("Failed to find the parent domain\n"); 201 - return -ENXIO; 202 - } 190 + struct pch_msi_data *priv; 203 191 204 192 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 205 193 if (!priv) ··· 199 203 200 204 mutex_init(&priv->msi_map_lock); 201 205 202 - ret = of_address_to_resource(node, 0, &res); 203 - if (ret) { 204 - pr_err("Failed to allocate resource\n"); 205 - goto err_priv; 206 - } 207 - 208 - priv->doorbell = res.start; 209 - 210 - if (of_property_read_u32(node, "loongson,msi-base-vec", 211 - &priv->irq_first)) { 212 - pr_err("Unable to parse MSI vec base\n"); 213 - ret = -EINVAL; 214 - goto err_priv; 215 - } 216 - 217 - if (of_property_read_u32(node, "loongson,msi-num-vecs", 218 - &priv->num_irqs)) { 219 - pr_err("Unable to parse MSI vec number\n"); 220 - ret = -EINVAL; 221 - goto err_priv; 222 - } 206 + priv->doorbell = msg_address; 207 + priv->irq_first = irq_base; 208 + priv->num_irqs = irq_count; 223 209 224 210 priv->msi_map = bitmap_zalloc(priv->num_irqs, GFP_KERNEL); 225 - if (!priv->msi_map) { 226 - ret = -ENOMEM; 211 + if (!priv->msi_map) 227 212 goto err_priv; 228 - } 229 213 230 214 pr_debug("Registering %d MSIs, starting at %d\n", 231 215 priv->num_irqs, priv->irq_first); 232 216 233 - ret = pch_msi_init_domains(priv, node, parent_domain); 217 + ret = pch_msi_init_domains(priv, parent_domain, domain_handle); 234 218 if (ret) 235 219 goto err_map; 236 220 221 + pch_msi_handle[nr_pics++] = domain_handle; 237 222 return 0; 238 223 239 224 err_map: 240 225 bitmap_free(priv->msi_map); 241 226 err_priv: 242 227 kfree(priv); 243 - return ret; 228 + 229 + return -EINVAL; 244 230 } 245 231 246 - IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_init); 232 + #ifdef CONFIG_OF 233 + static int pch_msi_of_init(struct device_node *node, struct device_node *parent) 234 + { 235 + int err; 236 + int irq_base, irq_count; 237 + struct resource res; 238 + struct irq_domain *parent_domain; 239 + 240 + parent_domain = irq_find_host(parent); 241 + if (!parent_domain) { 242 + pr_err("Failed to find the parent domain\n"); 243 + return -ENXIO; 244 + } 245 + 246 + if (of_address_to_resource(node, 0, &res)) { 247 + pr_err("Failed to allocate resource\n"); 248 + return -EINVAL; 249 + } 250 + 251 + if (of_property_read_u32(node, "loongson,msi-base-vec", &irq_base)) { 252 + pr_err("Unable to parse MSI vec base\n"); 253 + return -EINVAL; 254 + } 255 + 256 + if (of_property_read_u32(node, "loongson,msi-num-vecs", &irq_count)) { 257 + pr_err("Unable to parse MSI vec number\n"); 258 + return -EINVAL; 259 + } 260 + 261 + err = pch_msi_init(res.start, irq_base, irq_count, parent_domain, of_node_to_fwnode(node)); 262 + if (err < 0) 263 + return err; 264 + 265 + return 0; 266 + } 267 + 268 + IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_of_init); 269 + #endif 270 + 271 + #ifdef CONFIG_ACPI 272 + struct fwnode_handle *get_pch_msi_handle(int pci_segment) 273 + { 274 + int i; 275 + 276 + for (i = 0; i < MAX_IO_PICS; i++) { 277 + if (msi_group[i].pci_segment == pci_segment) 278 + return pch_msi_handle[i]; 279 + } 280 + return NULL; 281 + } 282 + 283 + int __init pch_msi_acpi_init(struct irq_domain *parent, 284 + struct acpi_madt_msi_pic *acpi_pchmsi) 285 + { 286 + int ret; 287 + struct fwnode_handle *domain_handle; 288 + 289 + domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_pchmsi); 290 + ret = pch_msi_init(acpi_pchmsi->msg_address, acpi_pchmsi->start, 291 + acpi_pchmsi->count, parent, domain_handle); 292 + if (ret < 0) 293 + irq_domain_free_fwnode(domain_handle); 294 + 295 + return ret; 296 + } 297 + #endif
+146 -31
drivers/irqchip/irq-loongson-pch-pic.c
··· 33 33 #define PIC_REG_IDX(irq_id) ((irq_id) / PIC_COUNT_PER_REG) 34 34 #define PIC_REG_BIT(irq_id) ((irq_id) % PIC_COUNT_PER_REG) 35 35 36 + static int nr_pics; 37 + 36 38 struct pch_pic { 37 39 void __iomem *base; 38 40 struct irq_domain *pic_domain; 39 41 u32 ht_vec_base; 40 42 raw_spinlock_t pic_lock; 43 + u32 vec_count; 44 + u32 gsi_base; 41 45 }; 46 + 47 + static struct pch_pic *pch_pic_priv[MAX_IO_PICS]; 48 + 49 + struct fwnode_handle *pch_pic_handle[MAX_IO_PICS]; 50 + 51 + int find_pch_pic(u32 gsi) 52 + { 53 + int i; 54 + 55 + /* Find the PCH_PIC that manages this GSI. */ 56 + for (i = 0; i < MAX_IO_PICS; i++) { 57 + struct pch_pic *priv = pch_pic_priv[i]; 58 + 59 + if (!priv) 60 + return -1; 61 + 62 + if (gsi >= priv->gsi_base && gsi < (priv->gsi_base + priv->vec_count)) 63 + return i; 64 + } 65 + 66 + pr_err("ERROR: Unable to locate PCH_PIC for GSI %d\n", gsi); 67 + return -1; 68 + } 42 69 43 70 static void pch_pic_bitset(struct pch_pic *priv, int offset, int bit) 44 71 { ··· 166 139 .irq_set_type = pch_pic_set_type, 167 140 }; 168 141 142 + static int pch_pic_domain_translate(struct irq_domain *d, 143 + struct irq_fwspec *fwspec, 144 + unsigned long *hwirq, 145 + unsigned int *type) 146 + { 147 + struct pch_pic *priv = d->host_data; 148 + struct device_node *of_node = to_of_node(fwspec->fwnode); 149 + 150 + if (fwspec->param_count < 1) 151 + return -EINVAL; 152 + 153 + if (of_node) { 154 + *hwirq = fwspec->param[0] + priv->ht_vec_base; 155 + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; 156 + } else { 157 + *hwirq = fwspec->param[0] - priv->gsi_base; 158 + *type = IRQ_TYPE_NONE; 159 + } 160 + 161 + return 0; 162 + } 163 + 169 164 static int pch_pic_alloc(struct irq_domain *domain, unsigned int virq, 170 165 unsigned int nr_irqs, void *arg) 171 166 { ··· 198 149 struct irq_fwspec parent_fwspec; 199 150 struct pch_pic *priv = domain->host_data; 200 151 201 - err = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type); 152 + err = pch_pic_domain_translate(domain, fwspec, &hwirq, &type); 202 153 if (err) 203 154 return err; 204 155 205 156 parent_fwspec.fwnode = domain->parent->fwnode; 206 157 parent_fwspec.param_count = 1; 207 - parent_fwspec.param[0] = hwirq + priv->ht_vec_base; 158 + parent_fwspec.param[0] = hwirq; 208 159 209 160 err = irq_domain_alloc_irqs_parent(domain, virq, 1, &parent_fwspec); 210 161 if (err) ··· 219 170 } 220 171 221 172 static const struct irq_domain_ops pch_pic_domain_ops = { 222 - .translate = irq_domain_translate_twocell, 173 + .translate = pch_pic_domain_translate, 223 174 .alloc = pch_pic_alloc, 224 175 .free = irq_domain_free_irqs_parent, 225 176 }; ··· 229 180 int i; 230 181 231 182 for (i = 0; i < PIC_COUNT; i++) { 232 - /* Write vectored ID */ 183 + /* Write vector ID */ 233 184 writeb(priv->ht_vec_base + i, priv->base + PCH_INT_HTVEC(i)); 234 185 /* Hardcode route to HT0 Lo */ 235 186 writeb(1, priv->base + PCH_INT_ROUTE(i)); ··· 247 198 } 248 199 } 249 200 250 - static int pch_pic_of_init(struct device_node *node, 251 - struct device_node *parent) 201 + static int pch_pic_init(phys_addr_t addr, unsigned long size, int vec_base, 202 + struct irq_domain *parent_domain, struct fwnode_handle *domain_handle, 203 + u32 gsi_base) 252 204 { 253 205 struct pch_pic *priv; 254 - struct irq_domain *parent_domain; 255 - int err; 256 206 257 207 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 258 208 if (!priv) 259 209 return -ENOMEM; 260 210 261 211 raw_spin_lock_init(&priv->pic_lock); 262 - priv->base = of_iomap(node, 0); 263 - if (!priv->base) { 264 - err = -ENOMEM; 212 + priv->base = ioremap(addr, size); 213 + if (!priv->base) 265 214 goto free_priv; 266 - } 267 215 268 - parent_domain = irq_find_host(parent); 269 - if (!parent_domain) { 270 - pr_err("Failed to find the parent domain\n"); 271 - err = -ENXIO; 272 - goto iounmap_base; 273 - } 274 - 275 - if (of_property_read_u32(node, "loongson,pic-base-vec", 276 - &priv->ht_vec_base)) { 277 - pr_err("Failed to determine pic-base-vec\n"); 278 - err = -EINVAL; 279 - goto iounmap_base; 280 - } 216 + priv->ht_vec_base = vec_base; 217 + priv->vec_count = ((readq(priv->base) >> 48) & 0xff) + 1; 218 + priv->gsi_base = gsi_base; 281 219 282 220 priv->pic_domain = irq_domain_create_hierarchy(parent_domain, 0, 283 - PIC_COUNT, 284 - of_node_to_fwnode(node), 285 - &pch_pic_domain_ops, 286 - priv); 221 + priv->vec_count, domain_handle, 222 + &pch_pic_domain_ops, priv); 223 + 287 224 if (!priv->pic_domain) { 288 225 pr_err("Failed to create IRQ domain\n"); 289 - err = -ENOMEM; 290 226 goto iounmap_base; 291 227 } 292 228 293 229 pch_pic_reset(priv); 230 + pch_pic_handle[nr_pics] = domain_handle; 231 + pch_pic_priv[nr_pics++] = priv; 294 232 295 233 return 0; 296 234 ··· 286 250 free_priv: 287 251 kfree(priv); 288 252 289 - return err; 253 + return -EINVAL; 254 + } 255 + 256 + #ifdef CONFIG_OF 257 + 258 + static int pch_pic_of_init(struct device_node *node, 259 + struct device_node *parent) 260 + { 261 + int err, vec_base; 262 + struct resource res; 263 + struct irq_domain *parent_domain; 264 + 265 + if (of_address_to_resource(node, 0, &res)) 266 + return -EINVAL; 267 + 268 + parent_domain = irq_find_host(parent); 269 + if (!parent_domain) { 270 + pr_err("Failed to find the parent domain\n"); 271 + return -ENXIO; 272 + } 273 + 274 + if (of_property_read_u32(node, "loongson,pic-base-vec", &vec_base)) { 275 + pr_err("Failed to determine pic-base-vec\n"); 276 + return -EINVAL; 277 + } 278 + 279 + err = pch_pic_init(res.start, resource_size(&res), vec_base, 280 + parent_domain, of_node_to_fwnode(node), 0); 281 + if (err < 0) 282 + return err; 283 + 284 + return 0; 290 285 } 291 286 292 287 IRQCHIP_DECLARE(pch_pic, "loongson,pch-pic-1.0", pch_pic_of_init); 288 + 289 + #endif 290 + 291 + #ifdef CONFIG_ACPI 292 + static int __init 293 + pch_lpc_parse_madt(union acpi_subtable_headers *header, 294 + const unsigned long end) 295 + { 296 + struct acpi_madt_lpc_pic *pchlpc_entry = (struct acpi_madt_lpc_pic *)header; 297 + 298 + return pch_lpc_acpi_init(pch_pic_priv[0]->pic_domain, pchlpc_entry); 299 + } 300 + 301 + static int __init acpi_cascade_irqdomain_init(void) 302 + { 303 + acpi_table_parse_madt(ACPI_MADT_TYPE_LPC_PIC, 304 + pch_lpc_parse_madt, 0); 305 + return 0; 306 + } 307 + 308 + int __init pch_pic_acpi_init(struct irq_domain *parent, 309 + struct acpi_madt_bio_pic *acpi_pchpic) 310 + { 311 + int ret, vec_base; 312 + struct fwnode_handle *domain_handle; 313 + 314 + vec_base = acpi_pchpic->gsi_base - GSI_MIN_PCH_IRQ; 315 + 316 + domain_handle = irq_domain_alloc_fwnode((phys_addr_t *)acpi_pchpic); 317 + if (!domain_handle) { 318 + pr_err("Unable to allocate domain handle\n"); 319 + return -ENOMEM; 320 + } 321 + 322 + ret = pch_pic_init(acpi_pchpic->address, acpi_pchpic->size, 323 + vec_base, parent, domain_handle, acpi_pchpic->gsi_base); 324 + 325 + if (ret < 0) { 326 + irq_domain_free_fwnode(domain_handle); 327 + return ret; 328 + } 329 + 330 + if (acpi_pchpic->id == 0) 331 + acpi_cascade_irqdomain_init(); 332 + 333 + return ret; 334 + } 335 + #endif
+58 -26
drivers/irqchip/irq-mips-gic.c
··· 52 52 53 53 static DEFINE_SPINLOCK(gic_lock); 54 54 static struct irq_domain *gic_irq_domain; 55 - static struct irq_domain *gic_ipi_domain; 56 55 static int gic_shared_intrs; 57 56 static unsigned int gic_cpu_pin; 58 57 static unsigned int timer_cpu_pin; 59 58 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller; 59 + 60 + #ifdef CONFIG_GENERIC_IRQ_IPI 60 61 static DECLARE_BITMAP(ipi_resrv, GIC_MAX_INTRS); 61 62 static DECLARE_BITMAP(ipi_available, GIC_MAX_INTRS); 63 + #endif /* CONFIG_GENERIC_IRQ_IPI */ 62 64 63 65 static struct gic_all_vpes_chip_data { 64 66 u32 map; ··· 474 472 u32 map; 475 473 476 474 if (hwirq >= GIC_SHARED_HWIRQ_BASE) { 475 + #ifdef CONFIG_GENERIC_IRQ_IPI 477 476 /* verify that shared irqs don't conflict with an IPI irq */ 478 477 if (test_bit(GIC_HWIRQ_TO_SHARED(hwirq), ipi_resrv)) 479 478 return -EBUSY; 479 + #endif /* CONFIG_GENERIC_IRQ_IPI */ 480 480 481 481 err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 482 482 &gic_level_irq_controller, ··· 570 566 .free = gic_irq_domain_free, 571 567 .map = gic_irq_domain_map, 572 568 }; 569 + 570 + #ifdef CONFIG_GENERIC_IRQ_IPI 573 571 574 572 static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, 575 573 const u32 *intspec, unsigned int intsize, ··· 676 670 .match = gic_ipi_domain_match, 677 671 }; 678 672 673 + static int gic_register_ipi_domain(struct device_node *node) 674 + { 675 + struct irq_domain *gic_ipi_domain; 676 + unsigned int v[2], num_ipis; 677 + 678 + gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, 679 + IRQ_DOMAIN_FLAG_IPI_PER_CPU, 680 + GIC_NUM_LOCAL_INTRS + gic_shared_intrs, 681 + node, &gic_ipi_domain_ops, NULL); 682 + if (!gic_ipi_domain) { 683 + pr_err("Failed to add IPI domain"); 684 + return -ENXIO; 685 + } 686 + 687 + irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI); 688 + 689 + if (node && 690 + !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) { 691 + bitmap_set(ipi_resrv, v[0], v[1]); 692 + } else { 693 + /* 694 + * Reserve 2 interrupts per possible CPU/VP for use as IPIs, 695 + * meeting the requirements of arch/mips SMP. 696 + */ 697 + num_ipis = 2 * num_possible_cpus(); 698 + bitmap_set(ipi_resrv, gic_shared_intrs - num_ipis, num_ipis); 699 + } 700 + 701 + bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS); 702 + 703 + return 0; 704 + } 705 + 706 + #else /* !CONFIG_GENERIC_IRQ_IPI */ 707 + 708 + static inline int gic_register_ipi_domain(struct device_node *node) 709 + { 710 + return 0; 711 + } 712 + 713 + #endif /* !CONFIG_GENERIC_IRQ_IPI */ 714 + 679 715 static int gic_cpu_startup(unsigned int cpu) 680 716 { 681 717 /* Enable or disable EIC */ ··· 736 688 static int __init gic_of_init(struct device_node *node, 737 689 struct device_node *parent) 738 690 { 739 - unsigned int cpu_vec, i, gicconfig, v[2], num_ipis; 691 + unsigned int cpu_vec, i, gicconfig; 740 692 unsigned long reserved; 741 693 phys_addr_t gic_base; 742 694 struct resource res; 743 695 size_t gic_len; 696 + int ret; 744 697 745 698 /* Find the first available CPU vector. */ 746 699 i = 0; ··· 783 734 } 784 735 785 736 mips_gic_base = ioremap(gic_base, gic_len); 737 + if (!mips_gic_base) { 738 + pr_err("Failed to ioremap gic_base\n"); 739 + return -ENOMEM; 740 + } 786 741 787 742 gicconfig = read_gic_config(); 788 743 gic_shared_intrs = FIELD_GET(GIC_CONFIG_NUMINTERRUPTS, gicconfig); ··· 833 780 return -ENXIO; 834 781 } 835 782 836 - gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, 837 - IRQ_DOMAIN_FLAG_IPI_PER_CPU, 838 - GIC_NUM_LOCAL_INTRS + gic_shared_intrs, 839 - node, &gic_ipi_domain_ops, NULL); 840 - if (!gic_ipi_domain) { 841 - pr_err("Failed to add IPI domain"); 842 - return -ENXIO; 843 - } 844 - 845 - irq_domain_update_bus_token(gic_ipi_domain, DOMAIN_BUS_IPI); 846 - 847 - if (node && 848 - !of_property_read_u32_array(node, "mti,reserved-ipi-vectors", v, 2)) { 849 - bitmap_set(ipi_resrv, v[0], v[1]); 850 - } else { 851 - /* 852 - * Reserve 2 interrupts per possible CPU/VP for use as IPIs, 853 - * meeting the requirements of arch/mips SMP. 854 - */ 855 - num_ipis = 2 * num_possible_cpus(); 856 - bitmap_set(ipi_resrv, gic_shared_intrs - num_ipis, num_ipis); 857 - } 858 - 859 - bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS); 783 + ret = gic_register_ipi_domain(node); 784 + if (ret) 785 + return ret; 860 786 861 787 board_bind_eic_interrupt = &gic_bind_eic_interrupt; 862 788
+393
drivers/irqchip/irq-renesas-rzg2l.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Renesas RZ/G2L IRQC Driver 4 + * 5 + * Copyright (C) 2022 Renesas Electronics Corporation. 6 + * 7 + * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com> 8 + */ 9 + 10 + #include <linux/bitfield.h> 11 + #include <linux/clk.h> 12 + #include <linux/err.h> 13 + #include <linux/io.h> 14 + #include <linux/irqchip.h> 15 + #include <linux/irqdomain.h> 16 + #include <linux/of_address.h> 17 + #include <linux/of_platform.h> 18 + #include <linux/pm_runtime.h> 19 + #include <linux/reset.h> 20 + #include <linux/spinlock.h> 21 + 22 + #define IRQC_IRQ_START 1 23 + #define IRQC_IRQ_COUNT 8 24 + #define IRQC_TINT_START (IRQC_IRQ_START + IRQC_IRQ_COUNT) 25 + #define IRQC_TINT_COUNT 32 26 + #define IRQC_NUM_IRQ (IRQC_TINT_START + IRQC_TINT_COUNT) 27 + 28 + #define ISCR 0x10 29 + #define IITSR 0x14 30 + #define TSCR 0x20 31 + #define TITSR0 0x24 32 + #define TITSR1 0x28 33 + #define TITSR0_MAX_INT 16 34 + #define TITSEL_WIDTH 0x2 35 + #define TSSR(n) (0x30 + ((n) * 4)) 36 + #define TIEN BIT(7) 37 + #define TSSEL_SHIFT(n) (8 * (n)) 38 + #define TSSEL_MASK GENMASK(7, 0) 39 + #define IRQ_MASK 0x3 40 + 41 + #define TSSR_OFFSET(n) ((n) % 4) 42 + #define TSSR_INDEX(n) ((n) / 4) 43 + 44 + #define TITSR_TITSEL_EDGE_RISING 0 45 + #define TITSR_TITSEL_EDGE_FALLING 1 46 + #define TITSR_TITSEL_LEVEL_HIGH 2 47 + #define TITSR_TITSEL_LEVEL_LOW 3 48 + 49 + #define IITSR_IITSEL(n, sense) ((sense) << ((n) * 2)) 50 + #define IITSR_IITSEL_LEVEL_LOW 0 51 + #define IITSR_IITSEL_EDGE_FALLING 1 52 + #define IITSR_IITSEL_EDGE_RISING 2 53 + #define IITSR_IITSEL_EDGE_BOTH 3 54 + #define IITSR_IITSEL_MASK(n) IITSR_IITSEL((n), 3) 55 + 56 + #define TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x)) 57 + #define TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x)) 58 + 59 + struct rzg2l_irqc_priv { 60 + void __iomem *base; 61 + struct irq_fwspec fwspec[IRQC_NUM_IRQ]; 62 + raw_spinlock_t lock; 63 + }; 64 + 65 + static struct rzg2l_irqc_priv *irq_data_to_priv(struct irq_data *data) 66 + { 67 + return data->domain->host_data; 68 + } 69 + 70 + static void rzg2l_irq_eoi(struct irq_data *d) 71 + { 72 + unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START; 73 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 74 + u32 bit = BIT(hw_irq); 75 + u32 reg; 76 + 77 + reg = readl_relaxed(priv->base + ISCR); 78 + if (reg & bit) 79 + writel_relaxed(reg & ~bit, priv->base + ISCR); 80 + } 81 + 82 + static void rzg2l_tint_eoi(struct irq_data *d) 83 + { 84 + unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_TINT_START; 85 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 86 + u32 bit = BIT(hw_irq); 87 + u32 reg; 88 + 89 + reg = readl_relaxed(priv->base + TSCR); 90 + if (reg & bit) 91 + writel_relaxed(reg & ~bit, priv->base + TSCR); 92 + } 93 + 94 + static void rzg2l_irqc_eoi(struct irq_data *d) 95 + { 96 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 97 + unsigned int hw_irq = irqd_to_hwirq(d); 98 + 99 + raw_spin_lock(&priv->lock); 100 + if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT) 101 + rzg2l_irq_eoi(d); 102 + else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) 103 + rzg2l_tint_eoi(d); 104 + raw_spin_unlock(&priv->lock); 105 + irq_chip_eoi_parent(d); 106 + } 107 + 108 + static void rzg2l_irqc_irq_disable(struct irq_data *d) 109 + { 110 + unsigned int hw_irq = irqd_to_hwirq(d); 111 + 112 + if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) { 113 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 114 + u32 offset = hw_irq - IRQC_TINT_START; 115 + u32 tssr_offset = TSSR_OFFSET(offset); 116 + u8 tssr_index = TSSR_INDEX(offset); 117 + u32 reg; 118 + 119 + raw_spin_lock(&priv->lock); 120 + reg = readl_relaxed(priv->base + TSSR(tssr_index)); 121 + reg &= ~(TSSEL_MASK << tssr_offset); 122 + writel_relaxed(reg, priv->base + TSSR(tssr_index)); 123 + raw_spin_unlock(&priv->lock); 124 + } 125 + irq_chip_disable_parent(d); 126 + } 127 + 128 + static void rzg2l_irqc_irq_enable(struct irq_data *d) 129 + { 130 + unsigned int hw_irq = irqd_to_hwirq(d); 131 + 132 + if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) { 133 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 134 + unsigned long tint = (uintptr_t)d->chip_data; 135 + u32 offset = hw_irq - IRQC_TINT_START; 136 + u32 tssr_offset = TSSR_OFFSET(offset); 137 + u8 tssr_index = TSSR_INDEX(offset); 138 + u32 reg; 139 + 140 + raw_spin_lock(&priv->lock); 141 + reg = readl_relaxed(priv->base + TSSR(tssr_index)); 142 + reg |= (TIEN | tint) << TSSEL_SHIFT(tssr_offset); 143 + writel_relaxed(reg, priv->base + TSSR(tssr_index)); 144 + raw_spin_unlock(&priv->lock); 145 + } 146 + irq_chip_enable_parent(d); 147 + } 148 + 149 + static int rzg2l_irq_set_type(struct irq_data *d, unsigned int type) 150 + { 151 + unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START; 152 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 153 + u16 sense, tmp; 154 + 155 + switch (type & IRQ_TYPE_SENSE_MASK) { 156 + case IRQ_TYPE_LEVEL_LOW: 157 + sense = IITSR_IITSEL_LEVEL_LOW; 158 + break; 159 + 160 + case IRQ_TYPE_EDGE_FALLING: 161 + sense = IITSR_IITSEL_EDGE_FALLING; 162 + break; 163 + 164 + case IRQ_TYPE_EDGE_RISING: 165 + sense = IITSR_IITSEL_EDGE_RISING; 166 + break; 167 + 168 + case IRQ_TYPE_EDGE_BOTH: 169 + sense = IITSR_IITSEL_EDGE_BOTH; 170 + break; 171 + 172 + default: 173 + return -EINVAL; 174 + } 175 + 176 + raw_spin_lock(&priv->lock); 177 + tmp = readl_relaxed(priv->base + IITSR); 178 + tmp &= ~IITSR_IITSEL_MASK(hw_irq); 179 + tmp |= IITSR_IITSEL(hw_irq, sense); 180 + writel_relaxed(tmp, priv->base + IITSR); 181 + raw_spin_unlock(&priv->lock); 182 + 183 + return 0; 184 + } 185 + 186 + static int rzg2l_tint_set_edge(struct irq_data *d, unsigned int type) 187 + { 188 + struct rzg2l_irqc_priv *priv = irq_data_to_priv(d); 189 + unsigned int hwirq = irqd_to_hwirq(d); 190 + u32 titseln = hwirq - IRQC_TINT_START; 191 + u32 offset; 192 + u8 sense; 193 + u32 reg; 194 + 195 + switch (type & IRQ_TYPE_SENSE_MASK) { 196 + case IRQ_TYPE_EDGE_RISING: 197 + sense = TITSR_TITSEL_EDGE_RISING; 198 + break; 199 + 200 + case IRQ_TYPE_EDGE_FALLING: 201 + sense = TITSR_TITSEL_EDGE_FALLING; 202 + break; 203 + 204 + default: 205 + return -EINVAL; 206 + } 207 + 208 + offset = TITSR0; 209 + if (titseln >= TITSR0_MAX_INT) { 210 + titseln -= TITSR0_MAX_INT; 211 + offset = TITSR1; 212 + } 213 + 214 + raw_spin_lock(&priv->lock); 215 + reg = readl_relaxed(priv->base + offset); 216 + reg &= ~(IRQ_MASK << (titseln * TITSEL_WIDTH)); 217 + reg |= sense << (titseln * TITSEL_WIDTH); 218 + writel_relaxed(reg, priv->base + offset); 219 + raw_spin_unlock(&priv->lock); 220 + 221 + return 0; 222 + } 223 + 224 + static int rzg2l_irqc_set_type(struct irq_data *d, unsigned int type) 225 + { 226 + unsigned int hw_irq = irqd_to_hwirq(d); 227 + int ret = -EINVAL; 228 + 229 + if (hw_irq >= IRQC_IRQ_START && hw_irq <= IRQC_IRQ_COUNT) 230 + ret = rzg2l_irq_set_type(d, type); 231 + else if (hw_irq >= IRQC_TINT_START && hw_irq < IRQC_NUM_IRQ) 232 + ret = rzg2l_tint_set_edge(d, type); 233 + if (ret) 234 + return ret; 235 + 236 + return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH); 237 + } 238 + 239 + static const struct irq_chip irqc_chip = { 240 + .name = "rzg2l-irqc", 241 + .irq_eoi = rzg2l_irqc_eoi, 242 + .irq_mask = irq_chip_mask_parent, 243 + .irq_unmask = irq_chip_unmask_parent, 244 + .irq_disable = rzg2l_irqc_irq_disable, 245 + .irq_enable = rzg2l_irqc_irq_enable, 246 + .irq_get_irqchip_state = irq_chip_get_parent_state, 247 + .irq_set_irqchip_state = irq_chip_set_parent_state, 248 + .irq_retrigger = irq_chip_retrigger_hierarchy, 249 + .irq_set_type = rzg2l_irqc_set_type, 250 + .flags = IRQCHIP_MASK_ON_SUSPEND | 251 + IRQCHIP_SET_TYPE_MASKED | 252 + IRQCHIP_SKIP_SET_WAKE, 253 + }; 254 + 255 + static int rzg2l_irqc_alloc(struct irq_domain *domain, unsigned int virq, 256 + unsigned int nr_irqs, void *arg) 257 + { 258 + struct rzg2l_irqc_priv *priv = domain->host_data; 259 + unsigned long tint = 0; 260 + irq_hw_number_t hwirq; 261 + unsigned int type; 262 + int ret; 263 + 264 + ret = irq_domain_translate_twocell(domain, arg, &hwirq, &type); 265 + if (ret) 266 + return ret; 267 + 268 + /* 269 + * For TINT interrupts ie where pinctrl driver is child of irqc domain 270 + * the hwirq and TINT are encoded in fwspec->param[0]. 271 + * hwirq for TINT range from 9-40, hwirq is embedded 0-15 bits and TINT 272 + * from 16-31 bits. TINT from the pinctrl driver needs to be programmed 273 + * in IRQC registers to enable a given gpio pin as interrupt. 274 + */ 275 + if (hwirq > IRQC_IRQ_COUNT) { 276 + tint = TINT_EXTRACT_GPIOINT(hwirq); 277 + hwirq = TINT_EXTRACT_HWIRQ(hwirq); 278 + 279 + if (hwirq < IRQC_TINT_START) 280 + return -EINVAL; 281 + } 282 + 283 + if (hwirq > (IRQC_NUM_IRQ - 1)) 284 + return -EINVAL; 285 + 286 + ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &irqc_chip, 287 + (void *)(uintptr_t)tint); 288 + if (ret) 289 + return ret; 290 + 291 + return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]); 292 + } 293 + 294 + static const struct irq_domain_ops rzg2l_irqc_domain_ops = { 295 + .alloc = rzg2l_irqc_alloc, 296 + .free = irq_domain_free_irqs_common, 297 + .translate = irq_domain_translate_twocell, 298 + }; 299 + 300 + static int rzg2l_irqc_parse_interrupts(struct rzg2l_irqc_priv *priv, 301 + struct device_node *np) 302 + { 303 + struct of_phandle_args map; 304 + unsigned int i; 305 + int ret; 306 + 307 + for (i = 0; i < IRQC_NUM_IRQ; i++) { 308 + ret = of_irq_parse_one(np, i, &map); 309 + if (ret) 310 + return ret; 311 + of_phandle_args_to_fwspec(np, map.args, map.args_count, 312 + &priv->fwspec[i]); 313 + } 314 + 315 + return 0; 316 + } 317 + 318 + static int rzg2l_irqc_init(struct device_node *node, struct device_node *parent) 319 + { 320 + struct irq_domain *irq_domain, *parent_domain; 321 + struct platform_device *pdev; 322 + struct reset_control *resetn; 323 + struct rzg2l_irqc_priv *priv; 324 + int ret; 325 + 326 + pdev = of_find_device_by_node(node); 327 + if (!pdev) 328 + return -ENODEV; 329 + 330 + parent_domain = irq_find_host(parent); 331 + if (!parent_domain) { 332 + dev_err(&pdev->dev, "cannot find parent domain\n"); 333 + return -ENODEV; 334 + } 335 + 336 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 337 + if (!priv) 338 + return -ENOMEM; 339 + 340 + priv->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL); 341 + if (IS_ERR(priv->base)) 342 + return PTR_ERR(priv->base); 343 + 344 + ret = rzg2l_irqc_parse_interrupts(priv, node); 345 + if (ret) { 346 + dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret); 347 + return ret; 348 + } 349 + 350 + resetn = devm_reset_control_get_exclusive(&pdev->dev, NULL); 351 + if (IS_ERR(resetn)) 352 + return PTR_ERR(resetn); 353 + 354 + ret = reset_control_deassert(resetn); 355 + if (ret) { 356 + dev_err(&pdev->dev, "failed to deassert resetn pin, %d\n", ret); 357 + return ret; 358 + } 359 + 360 + pm_runtime_enable(&pdev->dev); 361 + ret = pm_runtime_resume_and_get(&pdev->dev); 362 + if (ret < 0) { 363 + dev_err(&pdev->dev, "pm_runtime_resume_and_get failed: %d\n", ret); 364 + goto pm_disable; 365 + } 366 + 367 + raw_spin_lock_init(&priv->lock); 368 + 369 + irq_domain = irq_domain_add_hierarchy(parent_domain, 0, IRQC_NUM_IRQ, 370 + node, &rzg2l_irqc_domain_ops, 371 + priv); 372 + if (!irq_domain) { 373 + dev_err(&pdev->dev, "failed to add irq domain\n"); 374 + ret = -ENOMEM; 375 + goto pm_put; 376 + } 377 + 378 + return 0; 379 + 380 + pm_put: 381 + pm_runtime_put(&pdev->dev); 382 + pm_disable: 383 + pm_runtime_disable(&pdev->dev); 384 + reset_control_assert(resetn); 385 + return ret; 386 + } 387 + 388 + IRQCHIP_PLATFORM_DRIVER_BEGIN(rzg2l_irqc) 389 + IRQCHIP_MATCH("renesas,rzg2l-irqc", rzg2l_irqc_init) 390 + IRQCHIP_PLATFORM_DRIVER_END(rzg2l_irqc) 391 + MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>"); 392 + MODULE_DESCRIPTION("Renesas RZ/G2L IRQC Driver"); 393 + MODULE_LICENSE("GPL");
+108 -34
drivers/irqchip/irq-sifive-plic.c
··· 60 60 #define PLIC_DISABLE_THRESHOLD 0x7 61 61 #define PLIC_ENABLE_THRESHOLD 0 62 62 63 + #define PLIC_QUIRK_EDGE_INTERRUPT 0 64 + 63 65 struct plic_priv { 64 66 struct cpumask lmask; 65 67 struct irq_domain *irqdomain; 66 68 void __iomem *regs; 69 + unsigned long plic_quirks; 67 70 }; 68 71 69 72 struct plic_handler { ··· 83 80 static int plic_parent_irq __ro_after_init; 84 81 static bool plic_cpuhp_setup_done __ro_after_init; 85 82 static DEFINE_PER_CPU(struct plic_handler, plic_handlers); 83 + 84 + static int plic_irq_set_type(struct irq_data *d, unsigned int type); 86 85 87 86 static void __plic_toggle(void __iomem *enable_base, int hwirq, int enable) 88 87 { ··· 108 103 struct irq_data *d, int enable) 109 104 { 110 105 int cpu; 111 - struct plic_priv *priv = irq_data_get_irq_chip_data(d); 112 106 113 - writel(enable, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID); 114 107 for_each_cpu(cpu, mask) { 115 108 struct plic_handler *handler = per_cpu_ptr(&plic_handlers, cpu); 116 109 117 - if (handler->present && 118 - cpumask_test_cpu(cpu, &handler->priv->lmask)) 119 - plic_toggle(handler, d->hwirq, enable); 110 + plic_toggle(handler, d->hwirq, enable); 120 111 } 112 + } 113 + 114 + static void plic_irq_enable(struct irq_data *d) 115 + { 116 + plic_irq_toggle(irq_data_get_effective_affinity_mask(d), d, 1); 117 + } 118 + 119 + static void plic_irq_disable(struct irq_data *d) 120 + { 121 + plic_irq_toggle(irq_data_get_effective_affinity_mask(d), d, 0); 121 122 } 122 123 123 124 static void plic_irq_unmask(struct irq_data *d) 124 125 { 125 - struct cpumask amask; 126 - unsigned int cpu; 127 126 struct plic_priv *priv = irq_data_get_irq_chip_data(d); 128 127 129 - cpumask_and(&amask, &priv->lmask, cpu_online_mask); 130 - cpu = cpumask_any_and(irq_data_get_affinity_mask(d), 131 - &amask); 132 - if (WARN_ON_ONCE(cpu >= nr_cpu_ids)) 133 - return; 134 - plic_irq_toggle(cpumask_of(cpu), d, 1); 128 + writel(1, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID); 135 129 } 136 130 137 131 static void plic_irq_mask(struct irq_data *d) 138 132 { 139 133 struct plic_priv *priv = irq_data_get_irq_chip_data(d); 140 134 141 - plic_irq_toggle(&priv->lmask, d, 0); 135 + writel(0, priv->regs + PRIORITY_BASE + d->hwirq * PRIORITY_PER_ID); 136 + } 137 + 138 + static void plic_irq_eoi(struct irq_data *d) 139 + { 140 + struct plic_handler *handler = this_cpu_ptr(&plic_handlers); 141 + 142 + writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); 142 143 } 143 144 144 145 #ifdef CONFIG_SMP ··· 165 154 if (cpu >= nr_cpu_ids) 166 155 return -EINVAL; 167 156 168 - plic_irq_toggle(&priv->lmask, d, 0); 169 - plic_irq_toggle(cpumask_of(cpu), d, !irqd_irq_masked(d)); 157 + plic_irq_disable(d); 170 158 171 159 irq_data_update_effective_affinity(d, cpumask_of(cpu)); 160 + 161 + if (!irqd_irq_disabled(d)) 162 + plic_irq_enable(d); 172 163 173 164 return IRQ_SET_MASK_OK_DONE; 174 165 } 175 166 #endif 176 167 177 - static void plic_irq_eoi(struct irq_data *d) 178 - { 179 - struct plic_handler *handler = this_cpu_ptr(&plic_handlers); 180 - 181 - if (irqd_irq_masked(d)) { 182 - plic_irq_unmask(d); 183 - writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); 184 - plic_irq_mask(d); 185 - } else { 186 - writel(d->hwirq, handler->hart_base + CONTEXT_CLAIM); 187 - } 188 - } 168 + static struct irq_chip plic_edge_chip = { 169 + .name = "SiFive PLIC", 170 + .irq_enable = plic_irq_enable, 171 + .irq_disable = plic_irq_disable, 172 + .irq_ack = plic_irq_eoi, 173 + .irq_mask = plic_irq_mask, 174 + .irq_unmask = plic_irq_unmask, 175 + #ifdef CONFIG_SMP 176 + .irq_set_affinity = plic_set_affinity, 177 + #endif 178 + .irq_set_type = plic_irq_set_type, 179 + .flags = IRQCHIP_AFFINITY_PRE_STARTUP, 180 + }; 189 181 190 182 static struct irq_chip plic_chip = { 191 183 .name = "SiFive PLIC", 184 + .irq_enable = plic_irq_enable, 185 + .irq_disable = plic_irq_disable, 192 186 .irq_mask = plic_irq_mask, 193 187 .irq_unmask = plic_irq_unmask, 194 188 .irq_eoi = plic_irq_eoi, 195 189 #ifdef CONFIG_SMP 196 190 .irq_set_affinity = plic_set_affinity, 197 191 #endif 192 + .irq_set_type = plic_irq_set_type, 193 + .flags = IRQCHIP_AFFINITY_PRE_STARTUP, 198 194 }; 195 + 196 + static int plic_irq_set_type(struct irq_data *d, unsigned int type) 197 + { 198 + struct plic_priv *priv = irq_data_get_irq_chip_data(d); 199 + 200 + if (!test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) 201 + return IRQ_SET_MASK_OK_NOCOPY; 202 + 203 + switch (type) { 204 + case IRQ_TYPE_EDGE_RISING: 205 + irq_set_chip_handler_name_locked(d, &plic_edge_chip, 206 + handle_edge_irq, NULL); 207 + break; 208 + case IRQ_TYPE_LEVEL_HIGH: 209 + irq_set_chip_handler_name_locked(d, &plic_chip, 210 + handle_fasteoi_irq, NULL); 211 + break; 212 + default: 213 + return -EINVAL; 214 + } 215 + 216 + return IRQ_SET_MASK_OK; 217 + } 199 218 200 219 static int plic_irqdomain_map(struct irq_domain *d, unsigned int irq, 201 220 irq_hw_number_t hwirq) ··· 239 198 return 0; 240 199 } 241 200 201 + static int plic_irq_domain_translate(struct irq_domain *d, 202 + struct irq_fwspec *fwspec, 203 + unsigned long *hwirq, 204 + unsigned int *type) 205 + { 206 + struct plic_priv *priv = d->host_data; 207 + 208 + if (test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks)) 209 + return irq_domain_translate_twocell(d, fwspec, hwirq, type); 210 + 211 + return irq_domain_translate_onecell(d, fwspec, hwirq, type); 212 + } 213 + 242 214 static int plic_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, 243 215 unsigned int nr_irqs, void *arg) 244 216 { ··· 260 206 unsigned int type; 261 207 struct irq_fwspec *fwspec = arg; 262 208 263 - ret = irq_domain_translate_onecell(domain, fwspec, &hwirq, &type); 209 + ret = plic_irq_domain_translate(domain, fwspec, &hwirq, &type); 264 210 if (ret) 265 211 return ret; 266 212 ··· 274 220 } 275 221 276 222 static const struct irq_domain_ops plic_irqdomain_ops = { 277 - .translate = irq_domain_translate_onecell, 223 + .translate = plic_irq_domain_translate, 278 224 .alloc = plic_irq_domain_alloc, 279 225 .free = irq_domain_free_irqs_top, 280 226 }; ··· 335 281 return 0; 336 282 } 337 283 338 - static int __init plic_init(struct device_node *node, 339 - struct device_node *parent) 284 + static int __init __plic_init(struct device_node *node, 285 + struct device_node *parent, 286 + unsigned long plic_quirks) 340 287 { 341 288 int error = 0, nr_contexts, nr_handlers = 0, i; 342 289 u32 nr_irqs; ··· 347 292 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 348 293 if (!priv) 349 294 return -ENOMEM; 295 + 296 + priv->plic_quirks = plic_quirks; 350 297 351 298 priv->regs = of_iomap(node, 0); 352 299 if (WARN_ON(!priv->regs)) { ··· 439 382 i * CONTEXT_ENABLE_SIZE; 440 383 handler->priv = priv; 441 384 done: 442 - for (hwirq = 1; hwirq <= nr_irqs; hwirq++) 385 + for (hwirq = 1; hwirq <= nr_irqs; hwirq++) { 443 386 plic_toggle(handler, hwirq, 0); 387 + writel(1, priv->regs + PRIORITY_BASE + 388 + hwirq * PRIORITY_PER_ID); 389 + } 444 390 nr_handlers++; 445 391 } 446 392 ··· 470 410 return error; 471 411 } 472 412 413 + static int __init plic_init(struct device_node *node, 414 + struct device_node *parent) 415 + { 416 + return __plic_init(node, parent, 0); 417 + } 418 + 473 419 IRQCHIP_DECLARE(sifive_plic, "sifive,plic-1.0.0", plic_init); 474 420 IRQCHIP_DECLARE(riscv_plic0, "riscv,plic0", plic_init); /* for legacy systems */ 475 - IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_init); /* for firmware driver */ 421 + 422 + static int __init plic_edge_init(struct device_node *node, 423 + struct device_node *parent) 424 + { 425 + return __plic_init(node, parent, BIT(PLIC_QUIRK_EDGE_INTERRUPT)); 426 + } 427 + 428 + IRQCHIP_DECLARE(andestech_nceplic100, "andestech,nceplic100", plic_edge_init); 429 + IRQCHIP_DECLARE(thead_c900_plic, "thead,c900-plic", plic_edge_init);
+124 -126
drivers/irqchip/irq-stm32-exti.c
··· 34 34 u32 swier_ofst; 35 35 u32 rpr_ofst; 36 36 u32 fpr_ofst; 37 + u32 trg_ofst; 37 38 }; 38 39 39 40 #define UNDEF_REG ~0 40 41 41 - struct stm32_desc_irq { 42 - u32 exti; 43 - u32 irq_parent; 44 - struct irq_chip *chip; 45 - }; 46 - 47 42 struct stm32_exti_drv_data { 48 43 const struct stm32_exti_bank **exti_banks; 49 - const struct stm32_desc_irq *desc_irqs; 44 + const u8 *desc_irqs; 50 45 u32 bank_nr; 51 - u32 irq_nr; 52 46 }; 53 47 54 48 struct stm32_exti_chip_data { ··· 72 78 .swier_ofst = 0x10, 73 79 .rpr_ofst = 0x14, 74 80 .fpr_ofst = UNDEF_REG, 81 + .trg_ofst = UNDEF_REG, 75 82 }; 76 83 77 84 static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = { ··· 92 97 .swier_ofst = 0x08, 93 98 .rpr_ofst = 0x88, 94 99 .fpr_ofst = UNDEF_REG, 100 + .trg_ofst = UNDEF_REG, 95 101 }; 96 102 97 103 static const struct stm32_exti_bank stm32h7xx_exti_b2 = { ··· 103 107 .swier_ofst = 0x28, 104 108 .rpr_ofst = 0x98, 105 109 .fpr_ofst = UNDEF_REG, 110 + .trg_ofst = UNDEF_REG, 106 111 }; 107 112 108 113 static const struct stm32_exti_bank stm32h7xx_exti_b3 = { ··· 114 117 .swier_ofst = 0x48, 115 118 .rpr_ofst = 0xA8, 116 119 .fpr_ofst = UNDEF_REG, 120 + .trg_ofst = UNDEF_REG, 117 121 }; 118 122 119 123 static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = { ··· 130 132 131 133 static const struct stm32_exti_bank stm32mp1_exti_b1 = { 132 134 .imr_ofst = 0x80, 133 - .emr_ofst = 0x84, 135 + .emr_ofst = UNDEF_REG, 134 136 .rtsr_ofst = 0x00, 135 137 .ftsr_ofst = 0x04, 136 138 .swier_ofst = 0x08, 137 139 .rpr_ofst = 0x0C, 138 140 .fpr_ofst = 0x10, 141 + .trg_ofst = 0x3EC, 139 142 }; 140 143 141 144 static const struct stm32_exti_bank stm32mp1_exti_b2 = { 142 145 .imr_ofst = 0x90, 143 - .emr_ofst = 0x94, 146 + .emr_ofst = UNDEF_REG, 144 147 .rtsr_ofst = 0x20, 145 148 .ftsr_ofst = 0x24, 146 149 .swier_ofst = 0x28, 147 150 .rpr_ofst = 0x2C, 148 151 .fpr_ofst = 0x30, 152 + .trg_ofst = 0x3E8, 149 153 }; 150 154 151 155 static const struct stm32_exti_bank stm32mp1_exti_b3 = { 152 156 .imr_ofst = 0xA0, 153 - .emr_ofst = 0xA4, 157 + .emr_ofst = UNDEF_REG, 154 158 .rtsr_ofst = 0x40, 155 159 .ftsr_ofst = 0x44, 156 160 .swier_ofst = 0x48, 157 161 .rpr_ofst = 0x4C, 158 162 .fpr_ofst = 0x50, 163 + .trg_ofst = 0x3E4, 159 164 }; 160 165 161 166 static const struct stm32_exti_bank *stm32mp1_exti_banks[] = { ··· 170 169 static struct irq_chip stm32_exti_h_chip; 171 170 static struct irq_chip stm32_exti_h_chip_direct; 172 171 173 - static const struct stm32_desc_irq stm32mp1_desc_irq[] = { 174 - { .exti = 0, .irq_parent = 6, .chip = &stm32_exti_h_chip }, 175 - { .exti = 1, .irq_parent = 7, .chip = &stm32_exti_h_chip }, 176 - { .exti = 2, .irq_parent = 8, .chip = &stm32_exti_h_chip }, 177 - { .exti = 3, .irq_parent = 9, .chip = &stm32_exti_h_chip }, 178 - { .exti = 4, .irq_parent = 10, .chip = &stm32_exti_h_chip }, 179 - { .exti = 5, .irq_parent = 23, .chip = &stm32_exti_h_chip }, 180 - { .exti = 6, .irq_parent = 64, .chip = &stm32_exti_h_chip }, 181 - { .exti = 7, .irq_parent = 65, .chip = &stm32_exti_h_chip }, 182 - { .exti = 8, .irq_parent = 66, .chip = &stm32_exti_h_chip }, 183 - { .exti = 9, .irq_parent = 67, .chip = &stm32_exti_h_chip }, 184 - { .exti = 10, .irq_parent = 40, .chip = &stm32_exti_h_chip }, 185 - { .exti = 11, .irq_parent = 42, .chip = &stm32_exti_h_chip }, 186 - { .exti = 12, .irq_parent = 76, .chip = &stm32_exti_h_chip }, 187 - { .exti = 13, .irq_parent = 77, .chip = &stm32_exti_h_chip }, 188 - { .exti = 14, .irq_parent = 121, .chip = &stm32_exti_h_chip }, 189 - { .exti = 15, .irq_parent = 127, .chip = &stm32_exti_h_chip }, 190 - { .exti = 16, .irq_parent = 1, .chip = &stm32_exti_h_chip }, 191 - { .exti = 19, .irq_parent = 3, .chip = &stm32_exti_h_chip_direct }, 192 - { .exti = 21, .irq_parent = 31, .chip = &stm32_exti_h_chip_direct }, 193 - { .exti = 22, .irq_parent = 33, .chip = &stm32_exti_h_chip_direct }, 194 - { .exti = 23, .irq_parent = 72, .chip = &stm32_exti_h_chip_direct }, 195 - { .exti = 24, .irq_parent = 95, .chip = &stm32_exti_h_chip_direct }, 196 - { .exti = 25, .irq_parent = 107, .chip = &stm32_exti_h_chip_direct }, 197 - { .exti = 26, .irq_parent = 37, .chip = &stm32_exti_h_chip_direct }, 198 - { .exti = 27, .irq_parent = 38, .chip = &stm32_exti_h_chip_direct }, 199 - { .exti = 28, .irq_parent = 39, .chip = &stm32_exti_h_chip_direct }, 200 - { .exti = 29, .irq_parent = 71, .chip = &stm32_exti_h_chip_direct }, 201 - { .exti = 30, .irq_parent = 52, .chip = &stm32_exti_h_chip_direct }, 202 - { .exti = 31, .irq_parent = 53, .chip = &stm32_exti_h_chip_direct }, 203 - { .exti = 32, .irq_parent = 82, .chip = &stm32_exti_h_chip_direct }, 204 - { .exti = 33, .irq_parent = 83, .chip = &stm32_exti_h_chip_direct }, 205 - { .exti = 47, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct }, 206 - { .exti = 48, .irq_parent = 138, .chip = &stm32_exti_h_chip_direct }, 207 - { .exti = 50, .irq_parent = 139, .chip = &stm32_exti_h_chip_direct }, 208 - { .exti = 52, .irq_parent = 140, .chip = &stm32_exti_h_chip_direct }, 209 - { .exti = 53, .irq_parent = 141, .chip = &stm32_exti_h_chip_direct }, 210 - { .exti = 54, .irq_parent = 135, .chip = &stm32_exti_h_chip_direct }, 211 - { .exti = 61, .irq_parent = 100, .chip = &stm32_exti_h_chip_direct }, 212 - { .exti = 65, .irq_parent = 144, .chip = &stm32_exti_h_chip }, 213 - { .exti = 68, .irq_parent = 143, .chip = &stm32_exti_h_chip }, 214 - { .exti = 70, .irq_parent = 62, .chip = &stm32_exti_h_chip_direct }, 215 - { .exti = 73, .irq_parent = 129, .chip = &stm32_exti_h_chip }, 172 + #define EXTI_INVALID_IRQ U8_MAX 173 + #define STM32MP1_DESC_IRQ_SIZE (ARRAY_SIZE(stm32mp1_exti_banks) * IRQS_PER_BANK) 174 + 175 + static const u8 stm32mp1_desc_irq[] = { 176 + /* default value */ 177 + [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, 178 + 179 + [0] = 6, 180 + [1] = 7, 181 + [2] = 8, 182 + [3] = 9, 183 + [4] = 10, 184 + [5] = 23, 185 + [6] = 64, 186 + [7] = 65, 187 + [8] = 66, 188 + [9] = 67, 189 + [10] = 40, 190 + [11] = 42, 191 + [12] = 76, 192 + [13] = 77, 193 + [14] = 121, 194 + [15] = 127, 195 + [16] = 1, 196 + [19] = 3, 197 + [21] = 31, 198 + [22] = 33, 199 + [23] = 72, 200 + [24] = 95, 201 + [25] = 107, 202 + [26] = 37, 203 + [27] = 38, 204 + [28] = 39, 205 + [29] = 71, 206 + [30] = 52, 207 + [31] = 53, 208 + [32] = 82, 209 + [33] = 83, 210 + [47] = 93, 211 + [48] = 138, 212 + [50] = 139, 213 + [52] = 140, 214 + [53] = 141, 215 + [54] = 135, 216 + [61] = 100, 217 + [65] = 144, 218 + [68] = 143, 219 + [70] = 62, 220 + [73] = 129, 216 221 }; 217 222 218 - static const struct stm32_desc_irq stm32mp13_desc_irq[] = { 219 - { .exti = 0, .irq_parent = 6, .chip = &stm32_exti_h_chip }, 220 - { .exti = 1, .irq_parent = 7, .chip = &stm32_exti_h_chip }, 221 - { .exti = 2, .irq_parent = 8, .chip = &stm32_exti_h_chip }, 222 - { .exti = 3, .irq_parent = 9, .chip = &stm32_exti_h_chip }, 223 - { .exti = 4, .irq_parent = 10, .chip = &stm32_exti_h_chip }, 224 - { .exti = 5, .irq_parent = 24, .chip = &stm32_exti_h_chip }, 225 - { .exti = 6, .irq_parent = 65, .chip = &stm32_exti_h_chip }, 226 - { .exti = 7, .irq_parent = 66, .chip = &stm32_exti_h_chip }, 227 - { .exti = 8, .irq_parent = 67, .chip = &stm32_exti_h_chip }, 228 - { .exti = 9, .irq_parent = 68, .chip = &stm32_exti_h_chip }, 229 - { .exti = 10, .irq_parent = 41, .chip = &stm32_exti_h_chip }, 230 - { .exti = 11, .irq_parent = 43, .chip = &stm32_exti_h_chip }, 231 - { .exti = 12, .irq_parent = 77, .chip = &stm32_exti_h_chip }, 232 - { .exti = 13, .irq_parent = 78, .chip = &stm32_exti_h_chip }, 233 - { .exti = 14, .irq_parent = 106, .chip = &stm32_exti_h_chip }, 234 - { .exti = 15, .irq_parent = 109, .chip = &stm32_exti_h_chip }, 235 - { .exti = 16, .irq_parent = 1, .chip = &stm32_exti_h_chip }, 236 - { .exti = 19, .irq_parent = 3, .chip = &stm32_exti_h_chip_direct }, 237 - { .exti = 21, .irq_parent = 32, .chip = &stm32_exti_h_chip_direct }, 238 - { .exti = 22, .irq_parent = 34, .chip = &stm32_exti_h_chip_direct }, 239 - { .exti = 23, .irq_parent = 73, .chip = &stm32_exti_h_chip_direct }, 240 - { .exti = 24, .irq_parent = 93, .chip = &stm32_exti_h_chip_direct }, 241 - { .exti = 25, .irq_parent = 114, .chip = &stm32_exti_h_chip_direct }, 242 - { .exti = 26, .irq_parent = 38, .chip = &stm32_exti_h_chip_direct }, 243 - { .exti = 27, .irq_parent = 39, .chip = &stm32_exti_h_chip_direct }, 244 - { .exti = 28, .irq_parent = 40, .chip = &stm32_exti_h_chip_direct }, 245 - { .exti = 29, .irq_parent = 72, .chip = &stm32_exti_h_chip_direct }, 246 - { .exti = 30, .irq_parent = 53, .chip = &stm32_exti_h_chip_direct }, 247 - { .exti = 31, .irq_parent = 54, .chip = &stm32_exti_h_chip_direct }, 248 - { .exti = 32, .irq_parent = 83, .chip = &stm32_exti_h_chip_direct }, 249 - { .exti = 33, .irq_parent = 84, .chip = &stm32_exti_h_chip_direct }, 250 - { .exti = 44, .irq_parent = 96, .chip = &stm32_exti_h_chip_direct }, 251 - { .exti = 47, .irq_parent = 92, .chip = &stm32_exti_h_chip_direct }, 252 - { .exti = 48, .irq_parent = 116, .chip = &stm32_exti_h_chip_direct }, 253 - { .exti = 50, .irq_parent = 117, .chip = &stm32_exti_h_chip_direct }, 254 - { .exti = 52, .irq_parent = 118, .chip = &stm32_exti_h_chip_direct }, 255 - { .exti = 53, .irq_parent = 119, .chip = &stm32_exti_h_chip_direct }, 256 - { .exti = 68, .irq_parent = 63, .chip = &stm32_exti_h_chip_direct }, 257 - { .exti = 70, .irq_parent = 98, .chip = &stm32_exti_h_chip_direct }, 223 + static const u8 stm32mp13_desc_irq[] = { 224 + /* default value */ 225 + [0 ... (STM32MP1_DESC_IRQ_SIZE - 1)] = EXTI_INVALID_IRQ, 226 + 227 + [0] = 6, 228 + [1] = 7, 229 + [2] = 8, 230 + [3] = 9, 231 + [4] = 10, 232 + [5] = 24, 233 + [6] = 65, 234 + [7] = 66, 235 + [8] = 67, 236 + [9] = 68, 237 + [10] = 41, 238 + [11] = 43, 239 + [12] = 77, 240 + [13] = 78, 241 + [14] = 106, 242 + [15] = 109, 243 + [16] = 1, 244 + [19] = 3, 245 + [21] = 32, 246 + [22] = 34, 247 + [23] = 73, 248 + [24] = 93, 249 + [25] = 114, 250 + [26] = 38, 251 + [27] = 39, 252 + [28] = 40, 253 + [29] = 72, 254 + [30] = 53, 255 + [31] = 54, 256 + [32] = 83, 257 + [33] = 84, 258 + [44] = 96, 259 + [47] = 92, 260 + [48] = 116, 261 + [50] = 117, 262 + [52] = 118, 263 + [53] = 119, 264 + [68] = 63, 265 + [70] = 98, 258 266 }; 259 267 260 268 static const struct stm32_exti_drv_data stm32mp1_drv_data = { 261 269 .exti_banks = stm32mp1_exti_banks, 262 270 .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), 263 271 .desc_irqs = stm32mp1_desc_irq, 264 - .irq_nr = ARRAY_SIZE(stm32mp1_desc_irq), 265 272 }; 266 273 267 274 static const struct stm32_exti_drv_data stm32mp13_drv_data = { 268 275 .exti_banks = stm32mp1_exti_banks, 269 276 .bank_nr = ARRAY_SIZE(stm32mp1_exti_banks), 270 277 .desc_irqs = stm32mp13_desc_irq, 271 - .irq_nr = ARRAY_SIZE(stm32mp13_desc_irq), 272 278 }; 273 - 274 - static const struct 275 - stm32_desc_irq *stm32_exti_get_desc(const struct stm32_exti_drv_data *drv_data, 276 - irq_hw_number_t hwirq) 277 - { 278 - const struct stm32_desc_irq *desc = NULL; 279 - int i; 280 - 281 - if (!drv_data->desc_irqs) 282 - return NULL; 283 - 284 - for (i = 0; i < drv_data->irq_nr; i++) { 285 - desc = &drv_data->desc_irqs[i]; 286 - if (desc->exti == hwirq) 287 - break; 288 - } 289 - 290 - return desc; 291 - } 292 279 293 280 static unsigned long stm32_exti_pending(struct irq_chip_generic *gc) 294 281 { ··· 603 614 if (d->parent_data->chip) 604 615 return irq_chip_set_affinity_parent(d, dest, force); 605 616 606 - return -EINVAL; 617 + return IRQ_SET_MASK_OK_DONE; 607 618 } 608 619 609 620 static int __maybe_unused stm32_exti_h_suspend(void) ··· 680 691 .name = "stm32-exti-h-direct", 681 692 .irq_eoi = irq_chip_eoi_parent, 682 693 .irq_ack = irq_chip_ack_parent, 683 - .irq_mask = irq_chip_mask_parent, 684 - .irq_unmask = irq_chip_unmask_parent, 694 + .irq_mask = stm32_exti_h_mask, 695 + .irq_unmask = stm32_exti_h_unmask, 685 696 .irq_retrigger = irq_chip_retrigger_hierarchy, 686 697 .irq_set_type = irq_chip_set_type_parent, 687 698 .irq_set_wake = stm32_exti_h_set_wake, ··· 695 706 { 696 707 struct stm32_exti_host_data *host_data = dm->host_data; 697 708 struct stm32_exti_chip_data *chip_data; 698 - const struct stm32_desc_irq *desc; 709 + u8 desc_irq; 699 710 struct irq_fwspec *fwspec = data; 700 711 struct irq_fwspec p_fwspec; 701 712 irq_hw_number_t hwirq; 702 713 int bank; 714 + u32 event_trg; 715 + struct irq_chip *chip; 703 716 704 717 hwirq = fwspec->param[0]; 718 + if (hwirq >= host_data->drv_data->bank_nr * IRQS_PER_BANK) 719 + return -EINVAL; 720 + 705 721 bank = hwirq / IRQS_PER_BANK; 706 722 chip_data = &host_data->chips_data[bank]; 707 723 724 + event_trg = readl_relaxed(host_data->base + chip_data->reg_bank->trg_ofst); 725 + chip = (event_trg & BIT(hwirq % IRQS_PER_BANK)) ? 726 + &stm32_exti_h_chip : &stm32_exti_h_chip_direct; 708 727 709 - desc = stm32_exti_get_desc(host_data->drv_data, hwirq); 710 - if (!desc) 728 + irq_domain_set_hwirq_and_chip(dm, virq, hwirq, chip, chip_data); 729 + 730 + if (!host_data->drv_data || !host_data->drv_data->desc_irqs) 711 731 return -EINVAL; 712 732 713 - irq_domain_set_hwirq_and_chip(dm, virq, hwirq, desc->chip, 714 - chip_data); 715 - if (desc->irq_parent) { 733 + desc_irq = host_data->drv_data->desc_irqs[hwirq]; 734 + if (desc_irq != EXTI_INVALID_IRQ) { 716 735 p_fwspec.fwnode = dm->parent->fwnode; 717 736 p_fwspec.param_count = 3; 718 737 p_fwspec.param[0] = GIC_SPI; 719 - p_fwspec.param[1] = desc->irq_parent; 738 + p_fwspec.param[1] = desc_irq; 720 739 p_fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH; 721 740 722 741 return irq_domain_alloc_irqs_parent(dm, virq, 1, &p_fwspec); ··· 789 792 * clear registers to avoid residue 790 793 */ 791 794 writel_relaxed(0, base + stm32_bank->imr_ofst); 792 - writel_relaxed(0, base + stm32_bank->emr_ofst); 795 + if (stm32_bank->emr_ofst != UNDEF_REG) 796 + writel_relaxed(0, base + stm32_bank->emr_ofst); 793 797 794 798 pr_info("%pOF: bank%d\n", node, bank_idx); 795 799
+1 -1
drivers/parisc/iosapic.c
··· 677 677 if (dest_cpu < 0) 678 678 return -1; 679 679 680 - cpumask_copy(irq_data_get_affinity_mask(d), cpumask_of(dest_cpu)); 680 + irq_data_update_affinity(d, cpumask_of(dest_cpu)); 681 681 vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu); 682 682 683 683 spin_lock_irqsave(&iosapic_lock, flags);
+6 -6
drivers/pci/controller/pci-hyperv.c
··· 642 642 struct hv_retarget_device_interrupt *params; 643 643 struct tran_int_desc *int_desc; 644 644 struct hv_pcibus_device *hbus; 645 - struct cpumask *dest; 645 + const struct cpumask *dest; 646 646 cpumask_var_t tmp; 647 647 struct pci_bus *pbus; 648 648 struct pci_dev *pdev; ··· 1613 1613 } 1614 1614 1615 1615 static u32 hv_compose_msi_req_v1( 1616 - struct pci_create_interrupt *int_pkt, struct cpumask *affinity, 1616 + struct pci_create_interrupt *int_pkt, const struct cpumask *affinity, 1617 1617 u32 slot, u8 vector, u8 vector_count) 1618 1618 { 1619 1619 int_pkt->message_type.type = PCI_CREATE_INTERRUPT_MESSAGE; ··· 1635 1635 * Create MSI w/ dummy vCPU set targeting just one vCPU, overwritten 1636 1636 * by subsequent retarget in hv_irq_unmask(). 1637 1637 */ 1638 - static int hv_compose_msi_req_get_cpu(struct cpumask *affinity) 1638 + static int hv_compose_msi_req_get_cpu(const struct cpumask *affinity) 1639 1639 { 1640 1640 return cpumask_first_and(affinity, cpu_online_mask); 1641 1641 } 1642 1642 1643 1643 static u32 hv_compose_msi_req_v2( 1644 - struct pci_create_interrupt2 *int_pkt, struct cpumask *affinity, 1644 + struct pci_create_interrupt2 *int_pkt, const struct cpumask *affinity, 1645 1645 u32 slot, u8 vector, u8 vector_count) 1646 1646 { 1647 1647 int cpu; ··· 1660 1660 } 1661 1661 1662 1662 static u32 hv_compose_msi_req_v3( 1663 - struct pci_create_interrupt3 *int_pkt, struct cpumask *affinity, 1663 + struct pci_create_interrupt3 *int_pkt, const struct cpumask *affinity, 1664 1664 u32 slot, u32 vector, u8 vector_count) 1665 1665 { 1666 1666 int cpu; ··· 1697 1697 struct hv_pci_dev *hpdev; 1698 1698 struct pci_bus *pbus; 1699 1699 struct pci_dev *pdev; 1700 - struct cpumask *dest; 1700 + const struct cpumask *dest; 1701 1701 struct compose_comp_ctxt comp; 1702 1702 struct tran_int_desc *int_desc; 1703 1703 struct msi_desc *msi_desc;
+8 -2
drivers/pinctrl/pinctrl-ocelot.c
··· 1810 1810 1811 1811 regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), 1812 1812 BIT(gpio % 32), 0); 1813 + gpiochip_disable_irq(chip, gpio); 1813 1814 } 1814 1815 1815 1816 static void ocelot_irq_unmask(struct irq_data *data) ··· 1819 1818 struct ocelot_pinctrl *info = gpiochip_get_data(chip); 1820 1819 unsigned int gpio = irqd_to_hwirq(data); 1821 1820 1821 + gpiochip_enable_irq(chip, gpio); 1822 1822 regmap_update_bits(info->map, REG(OCELOT_GPIO_INTR_ENA, info, gpio), 1823 1823 BIT(gpio % 32), BIT(gpio % 32)); 1824 1824 } ··· 1841 1839 .irq_mask = ocelot_irq_mask, 1842 1840 .irq_eoi = ocelot_irq_ack, 1843 1841 .irq_unmask = ocelot_irq_unmask, 1844 - .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED, 1842 + .flags = IRQCHIP_EOI_THREADED | IRQCHIP_EOI_IF_HANDLED | 1843 + IRQCHIP_IMMUTABLE, 1845 1844 .irq_set_type = ocelot_irq_set_type, 1845 + GPIOCHIP_IRQ_RESOURCE_HELPERS 1846 1846 }; 1847 1847 1848 1848 static struct irq_chip ocelot_irqchip = { ··· 1853 1849 .irq_ack = ocelot_irq_ack, 1854 1850 .irq_unmask = ocelot_irq_unmask, 1855 1851 .irq_set_type = ocelot_irq_set_type, 1852 + .flags = IRQCHIP_IMMUTABLE, 1853 + GPIOCHIP_IRQ_RESOURCE_HELPERS 1856 1854 }; 1857 1855 1858 1856 static int ocelot_irq_set_type(struct irq_data *data, unsigned int type) ··· 1918 1912 irq = platform_get_irq_optional(pdev, 0); 1919 1913 if (irq > 0) { 1920 1914 girq = &gc->irq; 1921 - girq->chip = &ocelot_irqchip; 1915 + gpio_irq_chip_set_chip(girq, &ocelot_irqchip); 1922 1916 girq->parent_handler = ocelot_irq_handler; 1923 1917 girq->num_parents = 1; 1924 1918 girq->parents = devm_kcalloc(&pdev->dev, 1,
+6 -9
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
··· 966 966 return 0; 967 967 } 968 968 969 - static void *pmic_gpio_populate_parent_fwspec(struct gpio_chip *chip, 970 - unsigned int parent_hwirq, 971 - unsigned int parent_type) 969 + static int pmic_gpio_populate_parent_fwspec(struct gpio_chip *chip, 970 + union gpio_irq_fwspec *gfwspec, 971 + unsigned int parent_hwirq, 972 + unsigned int parent_type) 972 973 { 973 974 struct pmic_gpio_state *state = gpiochip_get_data(chip); 974 - struct irq_fwspec *fwspec; 975 - 976 - fwspec = kzalloc(sizeof(*fwspec), GFP_KERNEL); 977 - if (!fwspec) 978 - return NULL; 975 + struct irq_fwspec *fwspec = &gfwspec->fwspec; 979 976 980 977 fwspec->fwnode = chip->irq.parent_domain->fwnode; 981 978 ··· 982 985 /* param[2] must be left as 0 */ 983 986 fwspec->param[3] = parent_type; 984 987 985 - return fwspec; 988 + return 0; 986 989 } 987 990 988 991 static int pmic_gpio_probe(struct platform_device *pdev)
+233
drivers/pinctrl/renesas/pinctrl-rzg2l.c
··· 9 9 #include <linux/clk.h> 10 10 #include <linux/gpio/driver.h> 11 11 #include <linux/io.h> 12 + #include <linux/interrupt.h> 12 13 #include <linux/module.h> 13 14 #include <linux/of_device.h> 15 + #include <linux/of_irq.h> 14 16 #include <linux/pinctrl/pinconf-generic.h> 15 17 #include <linux/pinctrl/pinconf.h> 16 18 #include <linux/pinctrl/pinctrl.h> ··· 91 89 #define PIN(n) (0x0800 + 0x10 + (n)) 92 90 #define IOLH(n) (0x1000 + (n) * 8) 93 91 #define IEN(n) (0x1800 + (n) * 8) 92 + #define ISEL(n) (0x2c80 + (n) * 8) 94 93 #define PWPR (0x3014) 95 94 #define SD_CH(n) (0x3000 + (n) * 4) 96 95 #define QSPI (0x3008) ··· 114 111 #define RZG2L_PIN_ID_TO_PORT(id) ((id) / RZG2L_PINS_PER_PORT) 115 112 #define RZG2L_PIN_ID_TO_PORT_OFFSET(id) (RZG2L_PIN_ID_TO_PORT(id) + 0x10) 116 113 #define RZG2L_PIN_ID_TO_PIN(id) ((id) % RZG2L_PINS_PER_PORT) 114 + 115 + #define RZG2L_TINT_MAX_INTERRUPT 32 116 + #define RZG2L_TINT_IRQ_START_INDEX 9 117 + #define RZG2L_PACK_HWIRQ(t, i) (((t) << 16) | (i)) 117 118 118 119 struct rzg2l_dedicated_configs { 119 120 const char *name; ··· 144 137 145 138 struct gpio_chip gpio_chip; 146 139 struct pinctrl_gpio_range gpio_range; 140 + DECLARE_BITMAP(tint_slot, RZG2L_TINT_MAX_INTERRUPT); 141 + spinlock_t bitmap_lock; 142 + unsigned int hwirq[RZG2L_TINT_MAX_INTERRUPT]; 147 143 148 144 spinlock_t lock; 149 145 }; ··· 893 883 894 884 static void rzg2l_gpio_free(struct gpio_chip *chip, unsigned int offset) 895 885 { 886 + unsigned int virq; 887 + 896 888 pinctrl_gpio_free(chip->base + offset); 889 + 890 + virq = irq_find_mapping(chip->irq.domain, offset); 891 + if (virq) 892 + irq_dispose_mapping(virq); 897 893 898 894 /* 899 895 * Set the GPIO as an input to ensure that the next GPIO request won't ··· 1120 1104 } 1121 1105 }; 1122 1106 1107 + static int rzg2l_gpio_get_gpioint(unsigned int virq) 1108 + { 1109 + unsigned int gpioint; 1110 + unsigned int i; 1111 + u32 port, bit; 1112 + 1113 + port = virq / 8; 1114 + bit = virq % 8; 1115 + 1116 + if (port >= ARRAY_SIZE(rzg2l_gpio_configs) || 1117 + bit >= RZG2L_GPIO_PORT_GET_PINCNT(rzg2l_gpio_configs[port])) 1118 + return -EINVAL; 1119 + 1120 + gpioint = bit; 1121 + for (i = 0; i < port; i++) 1122 + gpioint += RZG2L_GPIO_PORT_GET_PINCNT(rzg2l_gpio_configs[i]); 1123 + 1124 + return gpioint; 1125 + } 1126 + 1127 + static void rzg2l_gpio_irq_disable(struct irq_data *d) 1128 + { 1129 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 1130 + struct rzg2l_pinctrl *pctrl = container_of(gc, struct rzg2l_pinctrl, gpio_chip); 1131 + unsigned int hwirq = irqd_to_hwirq(d); 1132 + unsigned long flags; 1133 + void __iomem *addr; 1134 + u32 port; 1135 + u8 bit; 1136 + 1137 + port = RZG2L_PIN_ID_TO_PORT(hwirq); 1138 + bit = RZG2L_PIN_ID_TO_PIN(hwirq); 1139 + 1140 + addr = pctrl->base + ISEL(port); 1141 + if (bit >= 4) { 1142 + bit -= 4; 1143 + addr += 4; 1144 + } 1145 + 1146 + spin_lock_irqsave(&pctrl->lock, flags); 1147 + writel(readl(addr) & ~BIT(bit * 8), addr); 1148 + spin_unlock_irqrestore(&pctrl->lock, flags); 1149 + 1150 + gpiochip_disable_irq(gc, hwirq); 1151 + irq_chip_disable_parent(d); 1152 + } 1153 + 1154 + static void rzg2l_gpio_irq_enable(struct irq_data *d) 1155 + { 1156 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 1157 + struct rzg2l_pinctrl *pctrl = container_of(gc, struct rzg2l_pinctrl, gpio_chip); 1158 + unsigned int hwirq = irqd_to_hwirq(d); 1159 + unsigned long flags; 1160 + void __iomem *addr; 1161 + u32 port; 1162 + u8 bit; 1163 + 1164 + gpiochip_enable_irq(gc, hwirq); 1165 + 1166 + port = RZG2L_PIN_ID_TO_PORT(hwirq); 1167 + bit = RZG2L_PIN_ID_TO_PIN(hwirq); 1168 + 1169 + addr = pctrl->base + ISEL(port); 1170 + if (bit >= 4) { 1171 + bit -= 4; 1172 + addr += 4; 1173 + } 1174 + 1175 + spin_lock_irqsave(&pctrl->lock, flags); 1176 + writel(readl(addr) | BIT(bit * 8), addr); 1177 + spin_unlock_irqrestore(&pctrl->lock, flags); 1178 + 1179 + irq_chip_enable_parent(d); 1180 + } 1181 + 1182 + static int rzg2l_gpio_irq_set_type(struct irq_data *d, unsigned int type) 1183 + { 1184 + return irq_chip_set_type_parent(d, type); 1185 + } 1186 + 1187 + static void rzg2l_gpio_irqc_eoi(struct irq_data *d) 1188 + { 1189 + irq_chip_eoi_parent(d); 1190 + } 1191 + 1192 + static void rzg2l_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p) 1193 + { 1194 + struct gpio_chip *gc = irq_data_get_irq_chip_data(data); 1195 + 1196 + seq_printf(p, dev_name(gc->parent)); 1197 + } 1198 + 1199 + static const struct irq_chip rzg2l_gpio_irqchip = { 1200 + .name = "rzg2l-gpio", 1201 + .irq_disable = rzg2l_gpio_irq_disable, 1202 + .irq_enable = rzg2l_gpio_irq_enable, 1203 + .irq_mask = irq_chip_mask_parent, 1204 + .irq_unmask = irq_chip_unmask_parent, 1205 + .irq_set_type = rzg2l_gpio_irq_set_type, 1206 + .irq_eoi = rzg2l_gpio_irqc_eoi, 1207 + .irq_print_chip = rzg2l_gpio_irq_print_chip, 1208 + .flags = IRQCHIP_IMMUTABLE, 1209 + GPIOCHIP_IRQ_RESOURCE_HELPERS, 1210 + }; 1211 + 1212 + static int rzg2l_gpio_child_to_parent_hwirq(struct gpio_chip *gc, 1213 + unsigned int child, 1214 + unsigned int child_type, 1215 + unsigned int *parent, 1216 + unsigned int *parent_type) 1217 + { 1218 + struct rzg2l_pinctrl *pctrl = gpiochip_get_data(gc); 1219 + unsigned long flags; 1220 + int gpioint, irq; 1221 + 1222 + gpioint = rzg2l_gpio_get_gpioint(child); 1223 + if (gpioint < 0) 1224 + return gpioint; 1225 + 1226 + spin_lock_irqsave(&pctrl->bitmap_lock, flags); 1227 + irq = bitmap_find_free_region(pctrl->tint_slot, RZG2L_TINT_MAX_INTERRUPT, get_order(1)); 1228 + spin_unlock_irqrestore(&pctrl->bitmap_lock, flags); 1229 + if (irq < 0) 1230 + return -ENOSPC; 1231 + pctrl->hwirq[irq] = child; 1232 + irq += RZG2L_TINT_IRQ_START_INDEX; 1233 + 1234 + /* All these interrupts are level high in the CPU */ 1235 + *parent_type = IRQ_TYPE_LEVEL_HIGH; 1236 + *parent = RZG2L_PACK_HWIRQ(gpioint, irq); 1237 + return 0; 1238 + } 1239 + 1240 + static int rzg2l_gpio_populate_parent_fwspec(struct gpio_chip *chip, 1241 + union gpio_irq_fwspec *gfwspec, 1242 + unsigned int parent_hwirq, 1243 + unsigned int parent_type) 1244 + { 1245 + struct irq_fwspec *fwspec = &gfwspec->fwspec; 1246 + 1247 + fwspec->fwnode = chip->irq.parent_domain->fwnode; 1248 + fwspec->param_count = 2; 1249 + fwspec->param[0] = parent_hwirq; 1250 + fwspec->param[1] = parent_type; 1251 + 1252 + return 0; 1253 + } 1254 + 1255 + static void rzg2l_gpio_irq_domain_free(struct irq_domain *domain, unsigned int virq, 1256 + unsigned int nr_irqs) 1257 + { 1258 + struct irq_data *d; 1259 + 1260 + d = irq_domain_get_irq_data(domain, virq); 1261 + if (d) { 1262 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 1263 + struct rzg2l_pinctrl *pctrl = container_of(gc, struct rzg2l_pinctrl, gpio_chip); 1264 + irq_hw_number_t hwirq = irqd_to_hwirq(d); 1265 + unsigned long flags; 1266 + unsigned int i; 1267 + 1268 + for (i = 0; i < RZG2L_TINT_MAX_INTERRUPT; i++) { 1269 + if (pctrl->hwirq[i] == hwirq) { 1270 + spin_lock_irqsave(&pctrl->bitmap_lock, flags); 1271 + bitmap_release_region(pctrl->tint_slot, i, get_order(1)); 1272 + spin_unlock_irqrestore(&pctrl->bitmap_lock, flags); 1273 + pctrl->hwirq[i] = 0; 1274 + break; 1275 + } 1276 + } 1277 + } 1278 + irq_domain_free_irqs_common(domain, virq, nr_irqs); 1279 + } 1280 + 1281 + static void rzg2l_init_irq_valid_mask(struct gpio_chip *gc, 1282 + unsigned long *valid_mask, 1283 + unsigned int ngpios) 1284 + { 1285 + struct rzg2l_pinctrl *pctrl = gpiochip_get_data(gc); 1286 + struct gpio_chip *chip = &pctrl->gpio_chip; 1287 + unsigned int offset; 1288 + 1289 + /* Forbid unused lines to be mapped as IRQs */ 1290 + for (offset = 0; offset < chip->ngpio; offset++) { 1291 + u32 port, bit; 1292 + 1293 + port = offset / 8; 1294 + bit = offset % 8; 1295 + 1296 + if (port >= ARRAY_SIZE(rzg2l_gpio_configs) || 1297 + bit >= RZG2L_GPIO_PORT_GET_PINCNT(rzg2l_gpio_configs[port])) 1298 + clear_bit(offset, valid_mask); 1299 + } 1300 + } 1301 + 1123 1302 static int rzg2l_gpio_register(struct rzg2l_pinctrl *pctrl) 1124 1303 { 1125 1304 struct device_node *np = pctrl->dev->of_node; 1126 1305 struct gpio_chip *chip = &pctrl->gpio_chip; 1127 1306 const char *name = dev_name(pctrl->dev); 1307 + struct irq_domain *parent_domain; 1128 1308 struct of_phandle_args of_args; 1309 + struct device_node *parent_np; 1310 + struct gpio_irq_chip *girq; 1129 1311 int ret; 1312 + 1313 + parent_np = of_irq_find_parent(np); 1314 + if (!parent_np) 1315 + return -ENXIO; 1316 + 1317 + parent_domain = irq_find_host(parent_np); 1318 + of_node_put(parent_np); 1319 + if (!parent_domain) 1320 + return -EPROBE_DEFER; 1130 1321 1131 1322 ret = of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &of_args); 1132 1323 if (ret) { ··· 1360 1137 chip->owner = THIS_MODULE; 1361 1138 chip->base = -1; 1362 1139 chip->ngpio = of_args.args[2]; 1140 + 1141 + girq = &chip->irq; 1142 + gpio_irq_chip_set_chip(girq, &rzg2l_gpio_irqchip); 1143 + girq->fwnode = of_node_to_fwnode(np); 1144 + girq->parent_domain = parent_domain; 1145 + girq->child_to_parent_hwirq = rzg2l_gpio_child_to_parent_hwirq; 1146 + girq->populate_parent_alloc_arg = rzg2l_gpio_populate_parent_fwspec; 1147 + girq->child_irq_domain_ops.free = rzg2l_gpio_irq_domain_free; 1148 + girq->init_valid_mask = rzg2l_init_irq_valid_mask; 1363 1149 1364 1150 pctrl->gpio_range.id = 0; 1365 1151 pctrl->gpio_range.pin_base = 0; ··· 1485 1253 } 1486 1254 1487 1255 spin_lock_init(&pctrl->lock); 1256 + spin_lock_init(&pctrl->bitmap_lock); 1488 1257 1489 1258 platform_set_drvdata(pdev, pctrl); 1490 1259
+1 -1
drivers/sh/intc/chip.c
··· 72 72 if (!cpumask_intersects(cpumask, cpu_online_mask)) 73 73 return -1; 74 74 75 - cpumask_copy(irq_data_get_affinity_mask(data), cpumask); 75 + irq_data_update_affinity(data, cpumask); 76 76 77 77 return IRQ_SET_MASK_OK_NOCOPY; 78 78 }
+4 -3
drivers/xen/events/events_base.c
··· 528 528 BUG_ON(irq == -1); 529 529 530 530 if (IS_ENABLED(CONFIG_SMP) && force_affinity) { 531 - cpumask_copy(irq_get_affinity_mask(irq), cpumask_of(cpu)); 532 - cpumask_copy(irq_get_effective_affinity_mask(irq), 533 - cpumask_of(cpu)); 531 + struct irq_data *data = irq_get_irq_data(irq); 532 + 533 + irq_data_update_affinity(data, cpumask_of(cpu)); 534 + irq_data_update_effective_affinity(data, cpumask_of(cpu)); 534 535 } 535 536 536 537 xen_evtchn_port_bind_to_cpu(evtchn, cpu, info->cpu);
+3 -1
include/linux/acpi.h
··· 105 105 ACPI_IRQ_MODEL_IOSAPIC, 106 106 ACPI_IRQ_MODEL_PLATFORM, 107 107 ACPI_IRQ_MODEL_GIC, 108 + ACPI_IRQ_MODEL_LPIC, 108 109 ACPI_IRQ_MODEL_COUNT 109 110 }; 110 111 ··· 357 356 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi); 358 357 359 358 void acpi_set_irq_model(enum acpi_irq_model_id model, 360 - struct fwnode_handle *fwnode); 359 + struct fwnode_handle *(*)(u32)); 360 + void acpi_set_gsi_to_irq_fallback(u32 (*)(u32)); 361 361 362 362 struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags, 363 363 unsigned int size,
+1
include/linux/cpuhotplug.h
··· 150 150 CPUHP_AP_IRQ_BCM2836_STARTING, 151 151 CPUHP_AP_IRQ_MIPS_GIC_STARTING, 152 152 CPUHP_AP_IRQ_RISCV_STARTING, 153 + CPUHP_AP_IRQ_LOONGARCH_STARTING, 153 154 CPUHP_AP_IRQ_SIFIVE_PLIC_STARTING, 154 155 CPUHP_AP_ARM_MVEBU_COHERENCY, 155 156 CPUHP_AP_MICROCODE_LOADER,
+19 -23
include/linux/gpio/driver.h
··· 12 12 #include <linux/property.h> 13 13 #include <linux/types.h> 14 14 15 + #include <asm/msi.h> 16 + 15 17 struct gpio_desc; 16 18 struct of_phandle_args; 17 19 struct device_node; ··· 24 22 enum gpio_lookup_flags; 25 23 26 24 struct gpio_chip; 25 + 26 + union gpio_irq_fwspec { 27 + struct irq_fwspec fwspec; 28 + #ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN 29 + msi_alloc_info_t msiinfo; 30 + #endif 31 + }; 27 32 28 33 #define GPIO_LINE_DIRECTION_IN 1 29 34 #define GPIO_LINE_DIRECTION_OUT 0 ··· 112 103 * variant named &gpiochip_populate_parent_fwspec_fourcell is also 113 104 * available. 114 105 */ 115 - void *(*populate_parent_alloc_arg)(struct gpio_chip *gc, 116 - unsigned int parent_hwirq, 117 - unsigned int parent_type); 106 + int (*populate_parent_alloc_arg)(struct gpio_chip *gc, 107 + union gpio_irq_fwspec *fwspec, 108 + unsigned int parent_hwirq, 109 + unsigned int parent_type); 118 110 119 111 /** 120 112 * @child_offset_to_irq: ··· 659 649 660 650 #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY 661 651 662 - void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, 652 + int gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, 653 + union gpio_irq_fwspec *gfwspec, 654 + unsigned int parent_hwirq, 655 + unsigned int parent_type); 656 + int gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, 657 + union gpio_irq_fwspec *gfwspec, 663 658 unsigned int parent_hwirq, 664 659 unsigned int parent_type); 665 - void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, 666 - unsigned int parent_hwirq, 667 - unsigned int parent_type); 668 - 669 - #else 670 - 671 - static inline void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *gc, 672 - unsigned int parent_hwirq, 673 - unsigned int parent_type) 674 - { 675 - return NULL; 676 - } 677 - 678 - static inline void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *gc, 679 - unsigned int parent_hwirq, 680 - unsigned int parent_type) 681 - { 682 - return NULL; 683 - } 684 660 685 661 #endif /* CONFIG_IRQ_DOMAIN_HIERARCHY */ 686 662
+28 -11
include/linux/irq.h
··· 151 151 #endif 152 152 void *handler_data; 153 153 struct msi_desc *msi_desc; 154 + #ifdef CONFIG_SMP 154 155 cpumask_var_t affinity; 156 + #endif 155 157 #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK 156 158 cpumask_var_t effective_affinity; 157 159 #endif ··· 881 879 return irq_common_data_get_node(d->common); 882 880 } 883 881 884 - static inline struct cpumask *irq_get_affinity_mask(int irq) 882 + static inline 883 + const struct cpumask *irq_data_get_affinity_mask(struct irq_data *d) 884 + { 885 + #ifdef CONFIG_SMP 886 + return d->common->affinity; 887 + #else 888 + return cpumask_of(0); 889 + #endif 890 + } 891 + 892 + static inline void irq_data_update_affinity(struct irq_data *d, 893 + const struct cpumask *m) 894 + { 895 + #ifdef CONFIG_SMP 896 + cpumask_copy(d->common->affinity, m); 897 + #endif 898 + } 899 + 900 + static inline const struct cpumask *irq_get_affinity_mask(int irq) 885 901 { 886 902 struct irq_data *d = irq_get_irq_data(irq); 887 903 888 - return d ? d->common->affinity : NULL; 889 - } 890 - 891 - static inline struct cpumask *irq_data_get_affinity_mask(struct irq_data *d) 892 - { 893 - return d->common->affinity; 904 + return d ? irq_data_get_affinity_mask(d) : NULL; 894 905 } 895 906 896 907 #ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK 897 908 static inline 898 - struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d) 909 + const struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d) 899 910 { 900 911 return d->common->effective_affinity; 901 912 } ··· 923 908 { 924 909 } 925 910 static inline 926 - struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d) 911 + const struct cpumask *irq_data_get_effective_affinity_mask(struct irq_data *d) 927 912 { 928 - return d->common->affinity; 913 + return irq_data_get_affinity_mask(d); 929 914 } 930 915 #endif 931 916 932 - static inline struct cpumask *irq_get_effective_affinity_mask(unsigned int irq) 917 + static inline 918 + const struct cpumask *irq_get_effective_affinity_mask(unsigned int irq) 933 919 { 934 920 struct irq_data *d = irq_get_irq_data(irq); 935 921 ··· 1137 1121 /* Setup functions for irq_chip_generic */ 1138 1122 int irq_map_generic_chip(struct irq_domain *d, unsigned int virq, 1139 1123 irq_hw_number_t hw_irq); 1124 + void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq); 1140 1125 struct irq_chip_generic * 1141 1126 irq_alloc_generic_chip(const char *name, int nr_ct, unsigned int irq_base, 1142 1127 void __iomem *reg_base, irq_flow_handler_t handler);
+3
include/linux/irqchip/mmp.h
··· 4 4 5 5 extern struct irq_chip icu_irq_chip; 6 6 7 + extern void icu_init_irq(void); 8 + extern void mmp2_init_icu(void); 9 + 7 10 #endif /* __IRQCHIP_MMP_H */
+3 -2
include/linux/irqdesc.h
··· 209 209 * Must be called with irq_desc locked and valid parameters. 210 210 */ 211 211 static inline void 212 - irq_set_chip_handler_name_locked(struct irq_data *data, struct irq_chip *chip, 212 + irq_set_chip_handler_name_locked(struct irq_data *data, 213 + const struct irq_chip *chip, 213 214 irq_flow_handler_t handler, const char *name) 214 215 { 215 216 struct irq_desc *desc = irq_data_to_desc(data); 216 217 217 218 desc->handle_irq = handler; 218 219 desc->name = name; 219 - data->chip = chip; 220 + data->chip = (struct irq_chip *)chip; 220 221 } 221 222 222 223 bool irq_check_status_bit(unsigned int irq, unsigned int bitmask);
+2
kernel/irq/Kconfig
··· 24 24 25 25 # Supports effective affinity mask 26 26 config GENERIC_IRQ_EFFECTIVE_AFF_MASK 27 + depends on SMP 27 28 bool 28 29 29 30 # Support for delayed migration from interrupt context ··· 83 82 # Generic IRQ IPI support 84 83 config GENERIC_IRQ_IPI 85 84 bool 85 + depends on SMP 86 86 select IRQ_DOMAIN_HIERARCHY 87 87 88 88 # Generic MSI interrupt support
+7 -4
kernel/irq/chip.c
··· 188 188 189 189 #ifdef CONFIG_SMP 190 190 static int 191 - __irq_startup_managed(struct irq_desc *desc, struct cpumask *aff, bool force) 191 + __irq_startup_managed(struct irq_desc *desc, const struct cpumask *aff, 192 + bool force) 192 193 { 193 194 struct irq_data *d = irq_desc_get_irq_data(desc); 194 195 ··· 225 224 } 226 225 #else 227 226 static __always_inline int 228 - __irq_startup_managed(struct irq_desc *desc, struct cpumask *aff, bool force) 227 + __irq_startup_managed(struct irq_desc *desc, const struct cpumask *aff, 228 + bool force) 229 229 { 230 230 return IRQ_STARTUP_NORMAL; 231 231 } ··· 254 252 int irq_startup(struct irq_desc *desc, bool resend, bool force) 255 253 { 256 254 struct irq_data *d = irq_desc_get_irq_data(desc); 257 - struct cpumask *aff = irq_data_get_affinity_mask(d); 255 + const struct cpumask *aff = irq_data_get_affinity_mask(d); 258 256 int ret = 0; 259 257 260 258 desc->depth = 0; ··· 1518 1516 if (data->chip->irq_request_resources) 1519 1517 return data->chip->irq_request_resources(data); 1520 1518 1521 - return -ENOSYS; 1519 + /* no error on missing optional irq_chip::irq_request_resources */ 1520 + return 0; 1522 1521 } 1523 1522 EXPORT_SYMBOL_GPL(irq_chip_request_resources_parent); 1524 1523
+1 -1
kernel/irq/debugfs.c
··· 30 30 static void irq_debug_show_masks(struct seq_file *m, struct irq_desc *desc) 31 31 { 32 32 struct irq_data *data = irq_desc_get_irq_data(desc); 33 - struct cpumask *msk; 33 + const struct cpumask *msk; 34 34 35 35 msk = irq_data_get_affinity_mask(data); 36 36 seq_printf(m, "affinity: %*pbl\n", cpumask_pr_args(msk));
+1 -1
kernel/irq/generic-chip.c
··· 431 431 return 0; 432 432 } 433 433 434 - static void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq) 434 + void irq_unmap_generic_chip(struct irq_domain *d, unsigned int virq) 435 435 { 436 436 struct irq_data *data = irq_domain_get_irq_data(d, virq); 437 437 struct irq_domain_chip_generic *dgc = d->gc;
+9 -7
kernel/irq/ipi.c
··· 115 115 int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest) 116 116 { 117 117 struct irq_data *data = irq_get_irq_data(irq); 118 - struct cpumask *ipimask = data ? irq_data_get_affinity_mask(data) : NULL; 118 + const struct cpumask *ipimask; 119 119 struct irq_domain *domain; 120 120 unsigned int nr_irqs; 121 121 122 - if (!irq || !data || !ipimask) 122 + if (!irq || !data) 123 123 return -EINVAL; 124 124 125 125 domain = data->domain; ··· 131 131 return -EINVAL; 132 132 } 133 133 134 - if (WARN_ON(!cpumask_subset(dest, ipimask))) 134 + ipimask = irq_data_get_affinity_mask(data); 135 + if (!ipimask || WARN_ON(!cpumask_subset(dest, ipimask))) 135 136 /* 136 137 * Must be destroying a subset of CPUs to which this IPI 137 138 * was set up to target ··· 163 162 irq_hw_number_t ipi_get_hwirq(unsigned int irq, unsigned int cpu) 164 163 { 165 164 struct irq_data *data = irq_get_irq_data(irq); 166 - struct cpumask *ipimask = data ? irq_data_get_affinity_mask(data) : NULL; 165 + const struct cpumask *ipimask; 167 166 168 - if (!data || !ipimask || cpu >= nr_cpu_ids) 167 + if (!data || cpu >= nr_cpu_ids) 169 168 return INVALID_HWIRQ; 170 169 171 - if (!cpumask_test_cpu(cpu, ipimask)) 170 + ipimask = irq_data_get_affinity_mask(data); 171 + if (!ipimask || !cpumask_test_cpu(cpu, ipimask)) 172 172 return INVALID_HWIRQ; 173 173 174 174 /* ··· 188 186 static int ipi_send_verify(struct irq_chip *chip, struct irq_data *data, 189 187 const struct cpumask *dest, unsigned int cpu) 190 188 { 191 - struct cpumask *ipimask = irq_data_get_affinity_mask(data); 189 + const struct cpumask *ipimask = irq_data_get_affinity_mask(data); 192 190 193 191 if (!chip || !ipimask) 194 192 return -EINVAL;
+1 -1
kernel/irq/irqdesc.c
··· 251 251 char *p = ""; 252 252 253 253 raw_spin_lock_irq(&desc->lock); 254 - for (action = desc->action; action != NULL; action = action->next) { 254 + for_each_action_of_desc(desc, action) { 255 255 ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", 256 256 p, action->name); 257 257 p = ",";
+8 -6
kernel/irq/irqdomain.c
··· 147 147 static atomic_t unknown_domains; 148 148 149 149 if (WARN_ON((size && direct_max) || 150 - (!IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) && direct_max))) 150 + (!IS_ENABLED(CONFIG_IRQ_DOMAIN_NOMAP) && direct_max) || 151 + (direct_max && (direct_max != hwirq_max)))) 151 152 return NULL; 152 153 153 154 domain = kzalloc_node(struct_size(domain, revmap, size), ··· 220 219 domain->hwirq_max = hwirq_max; 221 220 222 221 if (direct_max) { 223 - size = direct_max; 224 222 domain->flags |= IRQ_DOMAIN_FLAG_NO_MAP; 225 223 } 226 224 ··· 650 650 pr_debug("create_direct virq allocation failed\n"); 651 651 return 0; 652 652 } 653 - if (virq >= domain->revmap_size) { 654 - pr_err("ERROR: no free irqs available below %i maximum\n", 655 - domain->revmap_size); 653 + if (virq >= domain->hwirq_max) { 654 + pr_err("ERROR: no free irqs available below %lu maximum\n", 655 + domain->hwirq_max); 656 656 irq_free_desc(virq); 657 657 return 0; 658 658 } ··· 906 906 return desc; 907 907 908 908 if (irq_domain_is_nomap(domain)) { 909 - if (hwirq < domain->revmap_size) { 909 + if (hwirq < domain->hwirq_max) { 910 910 data = irq_domain_get_irq_data(domain, hwirq); 911 911 if (data && data->hwirq == hwirq) 912 912 desc = irq_data_to_desc(data); 913 + if (irq && desc) 914 + *irq = hwirq; 913 915 } 914 916 915 917 return desc;
+1 -9
kernel/irq/manage.c
··· 205 205 pr_warn_once("irq_chip %s did not update eff. affinity mask of irq %u\n", 206 206 chip->name, data->irq); 207 207 } 208 - 209 - static inline void irq_init_effective_affinity(struct irq_data *data, 210 - const struct cpumask *mask) 211 - { 212 - cpumask_copy(irq_data_get_effective_affinity_mask(data), mask); 213 - } 214 208 #else 215 209 static inline void irq_validate_effective_affinity(struct irq_data *data) { } 216 - static inline void irq_init_effective_affinity(struct irq_data *data, 217 - const struct cpumask *mask) { } 218 210 #endif 219 211 220 212 int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, ··· 339 347 return false; 340 348 341 349 cpumask_copy(desc->irq_common_data.affinity, mask); 342 - irq_init_effective_affinity(data, mask); 350 + irq_data_update_effective_affinity(data, mask); 343 351 irqd_set(data, IRQD_AFFINITY_SET); 344 352 return true; 345 353 }
-2
kernel/irq/pm.c
··· 147 147 synchronize_irq(irq); 148 148 } 149 149 } 150 - EXPORT_SYMBOL_GPL(suspend_device_irqs); 151 150 152 151 static void resume_irq(struct irq_desc *desc) 153 152 { ··· 258 259 { 259 260 resume_irqs(false); 260 261 } 261 - EXPORT_SYMBOL_GPL(resume_device_irqs);