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

Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq updates from Thomas Gleixner:
"Nothing exciting from the irq side for this merge window:

- a new driver for a Mediatek SoC

- ACPI support for ARM GICV3

- support for shared nested interrupts

- the usual pile of fixes and updates all over te place"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (28 commits)
irqchip/mbigen: Fix return value check in mbigen_device_probe()
irqchip/mips-gic: Replace static map with dynamic
irqchip/mips-gic: Remove device IRQ domain
irqchip/mips-gic: Separate IPI reservation & usage tracking
genirq: Use irqd_get_trigger_type to compare the trigger type for shared IRQs
genirq: Use cpumask_available() for check of cpumask variable
cpumask: Add helper cpumask_available()
irqchip/irq-imx-gpcv2: Clear OF_POPULATED flag
irqchip/atmel-aic5: Handle suspend to RAM
irqchip: Add Mediatek mtk-cirq driver
dt-bindings: mtk-cirq: Add binding document
irqchip/gic-v3-its: Add IORT hook for platform MSI support
irqchip/mbigen: Add ACPI support
irqchip/mbigen: Introduce mbigen_of_create_domain()
irqchip/mbigen: Drop module owner
platform-msi: Make platform_msi_create_device_domain() ACPI aware
irqchip/gicv3-its: platform-msi: Scan MADT to create platform msi domain
irqchip/gicv3-its: platform-msi: Refactor its_pmsi_init() to prepare for ACPI
irqchip/gicv3-its: platform-msi: Refactor its_pmsi_prepare()
irqchip/gic-v3-its: Keep the include header files in alphabetic order
...

+997 -615
+7 -4
Documentation/devicetree/bindings/interrupt-controller/cortina,gemini-interrupt-controller.txt Documentation/devicetree/bindings/interrupt-controller/faraday,ftintc010.txt
··· 1 - * Cortina Systems Gemini interrupt controller 1 + * Faraday Technologt FTINTC010 interrupt controller 2 2 3 - This interrupt controller is found on the Gemini SoCs. 3 + This interrupt controller is a stock IP block from Faraday Technology found 4 + in the Gemini SoCs and other designs. 4 5 5 6 Required properties: 6 - - compatible: must be "cortina,gemini-interrupt-controller" 7 + - compatible: must be one of 8 + "faraday,ftintc010" 9 + "cortina,gemini-interrupt-controller" (deprecated) 7 10 - reg: The register bank for the interrupt controller. 8 11 - interrupt-controller: Identifies the node as an interrupt controller 9 12 - #interrupt-cells: The number of cells to define the interrupts. ··· 18 15 Example: 19 16 20 17 interrupt-controller@48000000 { 21 - compatible = "cortina,gemini-interrupt-controller"; 18 + compatible = "faraday,ftintc010" 22 19 reg = <0x48000000 0x1000>; 23 20 interrupt-controller; 24 21 #interrupt-cells = <2>;
+35
Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt
··· 1 + * Mediatek 27xx cirq 2 + 3 + In Mediatek SOCs, the CIRQ is a low power interrupt controller designed to 4 + work outside MCUSYS which comprises with Cortex-Ax cores,CCI and GIC. 5 + The external interrupts (outside MCUSYS) will feed through CIRQ and connect 6 + to GIC in MCUSYS. When CIRQ is enabled, it will record the edge-sensitive 7 + interrupts and generate a pulse signal to parent interrupt controller when 8 + flush command is executed. With CIRQ, MCUSYS can be completely turned off 9 + to improve the system power consumption without losing interrupts. 10 + 11 + Required properties: 12 + - compatible: should be one of 13 + - "mediatek,mt2701-cirq" for mt2701 CIRQ 14 + - "mediatek,mt8135-cirq" for mt8135 CIRQ 15 + - "mediatek,mt8173-cirq" for mt8173 CIRQ 16 + and "mediatek,cirq" as a fallback. 17 + - interrupt-controller : Identifies the node as an interrupt controller. 18 + - #interrupt-cells : Use the same format as specified by GIC in arm,gic.txt. 19 + - interrupt-parent: phandle of irq parent for cirq. The parent must 20 + use the same interrupt-cells format as GIC. 21 + - reg: Physical base address of the cirq registers and length of memory 22 + mapped region. 23 + - mediatek,ext-irq-range: Identifies external irq number range in different 24 + SOCs. 25 + 26 + Example: 27 + cirq: interrupt-controller@10204000 { 28 + compatible = "mediatek,mt2701-cirq", 29 + "mediatek,mtk-cirq"; 30 + interrupt-controller; 31 + #interrupt-cells = <3>; 32 + interrupt-parent = <&sysirq>; 33 + reg = <0 0x10204000 0 0x400>; 34 + mediatek,ext-irq-start = <32 200>; 35 + };
+7 -4
Documentation/devicetree/bindings/interrupt-controller/mediatek,sysirq.txt
··· 21 21 - interrupt-parent: phandle of irq parent for sysirq. The parent must 22 22 use the same interrupt-cells format as GIC. 23 23 - reg: Physical base address of the intpol registers and length of memory 24 - mapped region. 24 + mapped region. Could be multiple bases here. Ex: mt6797 needs 2 reg, others 25 + need 1. 25 26 26 27 Example: 27 - sysirq: interrupt-controller@10200100 { 28 - compatible = "mediatek,mt6589-sysirq", "mediatek,mt6577-sysirq"; 28 + sysirq: intpol-controller@10200620 { 29 + compatible = "mediatek,mt6797-sysirq", 30 + "mediatek,mt6577-sysirq"; 29 31 interrupt-controller; 30 32 #interrupt-cells = <3>; 31 33 interrupt-parent = <&gic>; 32 - reg = <0 0x10200100 0 0x1c>; 34 + reg = <0 0x10220620 0 0x20>, 35 + <0 0x10220690 0 0x10>; 33 36 };
+1 -1
arch/arm/mach-moxart/Kconfig
··· 3 3 depends on ARCH_MULTI_V4 4 4 select CPU_FA526 5 5 select ARM_DMA_MEM_BUFFERABLE 6 + select FARADAY_FTINTC010 6 7 select MOXART_TIMER 7 - select GENERIC_IRQ_CHIP 8 8 select GPIOLIB 9 9 select PHYLIB if NETDEVICES 10 10 help
+1 -2
drivers/base/platform-msi.c
··· 345 345 346 346 data->host_data = host_data; 347 347 domain = irq_domain_create_hierarchy(dev->msi_domain, 0, nvec, 348 - of_node_to_fwnode(dev->of_node), 349 - ops, data); 348 + dev->fwnode, ops, data); 350 349 if (!domain) 351 350 goto free_priv; 352 351
+6
drivers/irqchip/Kconfig
··· 115 115 select GENERIC_IRQ_CHIP 116 116 select IRQ_DOMAIN 117 117 118 + config FARADAY_FTINTC010 119 + bool 120 + select IRQ_DOMAIN 121 + select MULTI_IRQ_HANDLER 122 + select SPARSE_IRQ 123 + 118 124 config HISILICON_IRQ_MBIGEN 119 125 bool 120 126 select ARM_GIC_V3
+2 -3
drivers/irqchip/Makefile
··· 6 6 obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o 7 7 obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o 8 8 obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o 9 - obj-$(CONFIG_ARCH_GEMINI) += irq-gemini.o 9 + obj-$(CONFIG_FARADAY_FTINTC010) += irq-ftintc010.o 10 10 obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o 11 11 obj-$(CONFIG_ARCH_LPC32XX) += irq-lpc32xx.o 12 12 obj-$(CONFIG_ARCH_MMP) += irq-mmp.o ··· 16 16 obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o 17 17 obj-$(CONFIG_METAG) += irq-metag-ext.o 18 18 obj-$(CONFIG_METAG_PERFCOUNTER_IRQS) += irq-metag.o 19 - obj-$(CONFIG_ARCH_MOXART) += irq-moxart.o 20 19 obj-$(CONFIG_CLPS711X_IRQCHIP) += irq-clps711x.o 21 20 obj-$(CONFIG_OR1K_PIC) += irq-or1k-pic.o 22 21 obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o ··· 61 62 obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o 62 63 obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o 63 64 obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o 64 - obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o 65 + obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o irq-mtk-cirq.o 65 66 obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o 66 67 obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o 67 68 obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
+28 -1
drivers/irqchip/irq-atmel-aic5.c
··· 150 150 } 151 151 152 152 #ifdef CONFIG_PM 153 + static u32 *smr_cache; 154 + 153 155 static void aic5_suspend(struct irq_data *d) 154 156 { 155 157 struct irq_domain *domain = d->domain; ··· 160 158 struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 161 159 int i; 162 160 u32 mask; 161 + 162 + if (smr_cache) 163 + for (i = 0; i < domain->revmap_size; i++) { 164 + irq_reg_writel(bgc, i, AT91_AIC5_SSR); 165 + smr_cache[i] = irq_reg_readl(bgc, AT91_AIC5_SMR); 166 + } 163 167 164 168 irq_gc_lock(bgc); 165 169 for (i = 0; i < dgc->irqs_per_chip; i++) { ··· 192 184 u32 mask; 193 185 194 186 irq_gc_lock(bgc); 187 + 188 + if (smr_cache) { 189 + irq_reg_writel(bgc, 0xffffffff, AT91_AIC5_SPU); 190 + for (i = 0; i < domain->revmap_size; i++) { 191 + irq_reg_writel(bgc, i, AT91_AIC5_SSR); 192 + irq_reg_writel(bgc, i, AT91_AIC5_SVR); 193 + irq_reg_writel(bgc, smr_cache[i], AT91_AIC5_SMR); 194 + } 195 + } 196 + 195 197 for (i = 0; i < dgc->irqs_per_chip; i++) { 196 198 mask = 1 << i; 197 - if ((mask & gc->mask_cache) == (mask & gc->wake_active)) 199 + 200 + if (!smr_cache && 201 + ((mask & gc->mask_cache) == (mask & gc->wake_active))) 198 202 continue; 199 203 200 204 irq_reg_writel(bgc, i + gc->irq_base, AT91_AIC5_SSR); ··· 362 342 static int __init sama5d2_aic5_of_init(struct device_node *node, 363 343 struct device_node *parent) 364 344 { 345 + #ifdef CONFIG_PM 346 + smr_cache = kcalloc(DIV_ROUND_UP(NR_SAMA5D2_IRQS, 32) * 32, 347 + sizeof(*smr_cache), GFP_KERNEL); 348 + if (!smr_cache) 349 + return -ENOMEM; 350 + #endif 351 + 365 352 return aic5_of_init(node, parent, NR_SAMA5D2_IRQS); 366 353 } 367 354 IRQCHIP_DECLARE(sama5d2_aic5, "atmel,sama5d2-aic", sama5d2_aic5_of_init);
+194
drivers/irqchip/irq-ftintc010.c
··· 1 + /* 2 + * irqchip for the Faraday Technology FTINTC010 Copyright (C) 2017 Linus 3 + * Walleij <linus.walleij@linaro.org> 4 + * 5 + * Based on arch/arm/mach-gemini/irq.c 6 + * Copyright (C) 2001-2006 Storlink, Corp. 7 + * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@gmail.com> 8 + */ 9 + #include <linux/bitops.h> 10 + #include <linux/irq.h> 11 + #include <linux/io.h> 12 + #include <linux/irqchip.h> 13 + #include <linux/irqchip/versatile-fpga.h> 14 + #include <linux/irqdomain.h> 15 + #include <linux/module.h> 16 + #include <linux/of.h> 17 + #include <linux/of_address.h> 18 + #include <linux/of_irq.h> 19 + #include <linux/cpu.h> 20 + 21 + #include <asm/exception.h> 22 + #include <asm/mach/irq.h> 23 + 24 + #define FT010_NUM_IRQS 32 25 + 26 + #define FT010_IRQ_SOURCE(base_addr) (base_addr + 0x00) 27 + #define FT010_IRQ_MASK(base_addr) (base_addr + 0x04) 28 + #define FT010_IRQ_CLEAR(base_addr) (base_addr + 0x08) 29 + /* Selects level- or edge-triggered */ 30 + #define FT010_IRQ_MODE(base_addr) (base_addr + 0x0C) 31 + /* Selects active low/high or falling/rising edge */ 32 + #define FT010_IRQ_POLARITY(base_addr) (base_addr + 0x10) 33 + #define FT010_IRQ_STATUS(base_addr) (base_addr + 0x14) 34 + #define FT010_FIQ_SOURCE(base_addr) (base_addr + 0x20) 35 + #define FT010_FIQ_MASK(base_addr) (base_addr + 0x24) 36 + #define FT010_FIQ_CLEAR(base_addr) (base_addr + 0x28) 37 + #define FT010_FIQ_MODE(base_addr) (base_addr + 0x2C) 38 + #define FT010_FIQ_POLARITY(base_addr) (base_addr + 0x30) 39 + #define FT010_FIQ_STATUS(base_addr) (base_addr + 0x34) 40 + 41 + /** 42 + * struct ft010_irq_data - irq data container for the Faraday IRQ controller 43 + * @base: memory offset in virtual memory 44 + * @chip: chip container for this instance 45 + * @domain: IRQ domain for this instance 46 + */ 47 + struct ft010_irq_data { 48 + void __iomem *base; 49 + struct irq_chip chip; 50 + struct irq_domain *domain; 51 + }; 52 + 53 + static void ft010_irq_mask(struct irq_data *d) 54 + { 55 + struct ft010_irq_data *f = irq_data_get_irq_chip_data(d); 56 + unsigned int mask; 57 + 58 + mask = readl(FT010_IRQ_MASK(f->base)); 59 + mask &= ~BIT(irqd_to_hwirq(d)); 60 + writel(mask, FT010_IRQ_MASK(f->base)); 61 + } 62 + 63 + static void ft010_irq_unmask(struct irq_data *d) 64 + { 65 + struct ft010_irq_data *f = irq_data_get_irq_chip_data(d); 66 + unsigned int mask; 67 + 68 + mask = readl(FT010_IRQ_MASK(f->base)); 69 + mask |= BIT(irqd_to_hwirq(d)); 70 + writel(mask, FT010_IRQ_MASK(f->base)); 71 + } 72 + 73 + static void ft010_irq_ack(struct irq_data *d) 74 + { 75 + struct ft010_irq_data *f = irq_data_get_irq_chip_data(d); 76 + 77 + writel(BIT(irqd_to_hwirq(d)), FT010_IRQ_CLEAR(f->base)); 78 + } 79 + 80 + static int ft010_irq_set_type(struct irq_data *d, unsigned int trigger) 81 + { 82 + struct ft010_irq_data *f = irq_data_get_irq_chip_data(d); 83 + int offset = irqd_to_hwirq(d); 84 + u32 mode, polarity; 85 + 86 + mode = readl(FT010_IRQ_MODE(f->base)); 87 + polarity = readl(FT010_IRQ_POLARITY(f->base)); 88 + 89 + if (trigger & (IRQ_TYPE_LEVEL_LOW)) { 90 + irq_set_handler_locked(d, handle_level_irq); 91 + mode &= ~BIT(offset); 92 + polarity |= BIT(offset); 93 + } else if (trigger & (IRQ_TYPE_LEVEL_HIGH)) { 94 + irq_set_handler_locked(d, handle_level_irq); 95 + mode &= ~BIT(offset); 96 + polarity &= ~BIT(offset); 97 + } else if (trigger & IRQ_TYPE_EDGE_FALLING) { 98 + irq_set_handler_locked(d, handle_edge_irq); 99 + mode |= BIT(offset); 100 + polarity |= BIT(offset); 101 + } else if (trigger & IRQ_TYPE_EDGE_RISING) { 102 + irq_set_handler_locked(d, handle_edge_irq); 103 + mode |= BIT(offset); 104 + polarity &= ~BIT(offset); 105 + } else { 106 + irq_set_handler_locked(d, handle_bad_irq); 107 + pr_warn("Faraday IRQ: no supported trigger selected for line %d\n", 108 + offset); 109 + } 110 + 111 + writel(mode, FT010_IRQ_MODE(f->base)); 112 + writel(polarity, FT010_IRQ_POLARITY(f->base)); 113 + 114 + return 0; 115 + } 116 + 117 + static struct irq_chip ft010_irq_chip = { 118 + .name = "FTINTC010", 119 + .irq_ack = ft010_irq_ack, 120 + .irq_mask = ft010_irq_mask, 121 + .irq_unmask = ft010_irq_unmask, 122 + .irq_set_type = ft010_irq_set_type, 123 + }; 124 + 125 + /* Local static for the IRQ entry call */ 126 + static struct ft010_irq_data firq; 127 + 128 + asmlinkage void __exception_irq_entry ft010_irqchip_handle_irq(struct pt_regs *regs) 129 + { 130 + struct ft010_irq_data *f = &firq; 131 + int irq; 132 + u32 status; 133 + 134 + while ((status = readl(FT010_IRQ_STATUS(f->base)))) { 135 + irq = ffs(status) - 1; 136 + handle_domain_irq(f->domain, irq, regs); 137 + } 138 + } 139 + 140 + static int ft010_irqdomain_map(struct irq_domain *d, unsigned int irq, 141 + irq_hw_number_t hwirq) 142 + { 143 + struct ft010_irq_data *f = d->host_data; 144 + 145 + irq_set_chip_data(irq, f); 146 + /* All IRQs should set up their type, flags as bad by default */ 147 + irq_set_chip_and_handler(irq, &ft010_irq_chip, handle_bad_irq); 148 + irq_set_probe(irq); 149 + 150 + return 0; 151 + } 152 + 153 + static void ft010_irqdomain_unmap(struct irq_domain *d, unsigned int irq) 154 + { 155 + irq_set_chip_and_handler(irq, NULL, NULL); 156 + irq_set_chip_data(irq, NULL); 157 + } 158 + 159 + static const struct irq_domain_ops ft010_irqdomain_ops = { 160 + .map = ft010_irqdomain_map, 161 + .unmap = ft010_irqdomain_unmap, 162 + .xlate = irq_domain_xlate_onetwocell, 163 + }; 164 + 165 + int __init ft010_of_init_irq(struct device_node *node, 166 + struct device_node *parent) 167 + { 168 + struct ft010_irq_data *f = &firq; 169 + 170 + /* 171 + * Disable the idle handler by default since it is buggy 172 + * For more info see arch/arm/mach-gemini/idle.c 173 + */ 174 + cpu_idle_poll_ctrl(true); 175 + 176 + f->base = of_iomap(node, 0); 177 + WARN(!f->base, "unable to map gemini irq registers\n"); 178 + 179 + /* Disable all interrupts */ 180 + writel(0, FT010_IRQ_MASK(f->base)); 181 + writel(0, FT010_FIQ_MASK(f->base)); 182 + 183 + f->domain = irq_domain_add_simple(node, FT010_NUM_IRQS, 0, 184 + &ft010_irqdomain_ops, f); 185 + set_handle_irq(ft010_irqchip_handle_irq); 186 + 187 + return 0; 188 + } 189 + IRQCHIP_DECLARE(faraday, "faraday,ftintc010", 190 + ft010_of_init_irq); 191 + IRQCHIP_DECLARE(gemini, "cortina,gemini-interrupt-controller", 192 + ft010_of_init_irq); 193 + IRQCHIP_DECLARE(moxa, "moxa,moxart-ic", 194 + ft010_of_init_irq);
-185
drivers/irqchip/irq-gemini.c
··· 1 - /* 2 - * irqchip for the Cortina Systems Gemini Copyright (C) 2017 Linus 3 - * Walleij <linus.walleij@linaro.org> 4 - * 5 - * Based on arch/arm/mach-gemini/irq.c 6 - * Copyright (C) 2001-2006 Storlink, Corp. 7 - * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt> 8 - */ 9 - #include <linux/bitops.h> 10 - #include <linux/irq.h> 11 - #include <linux/io.h> 12 - #include <linux/irqchip.h> 13 - #include <linux/irqchip/versatile-fpga.h> 14 - #include <linux/irqdomain.h> 15 - #include <linux/module.h> 16 - #include <linux/of.h> 17 - #include <linux/of_address.h> 18 - #include <linux/of_irq.h> 19 - #include <linux/cpu.h> 20 - 21 - #include <asm/exception.h> 22 - #include <asm/mach/irq.h> 23 - 24 - #define GEMINI_NUM_IRQS 32 25 - 26 - #define GEMINI_IRQ_SOURCE(base_addr) (base_addr + 0x00) 27 - #define GEMINI_IRQ_MASK(base_addr) (base_addr + 0x04) 28 - #define GEMINI_IRQ_CLEAR(base_addr) (base_addr + 0x08) 29 - #define GEMINI_IRQ_MODE(base_addr) (base_addr + 0x0C) 30 - #define GEMINI_IRQ_POLARITY(base_addr) (base_addr + 0x10) 31 - #define GEMINI_IRQ_STATUS(base_addr) (base_addr + 0x14) 32 - #define GEMINI_FIQ_SOURCE(base_addr) (base_addr + 0x20) 33 - #define GEMINI_FIQ_MASK(base_addr) (base_addr + 0x24) 34 - #define GEMINI_FIQ_CLEAR(base_addr) (base_addr + 0x28) 35 - #define GEMINI_FIQ_MODE(base_addr) (base_addr + 0x2C) 36 - #define GEMINI_FIQ_POLARITY(base_addr) (base_addr + 0x30) 37 - #define GEMINI_FIQ_STATUS(base_addr) (base_addr + 0x34) 38 - 39 - /** 40 - * struct gemini_irq_data - irq data container for the Gemini IRQ controller 41 - * @base: memory offset in virtual memory 42 - * @chip: chip container for this instance 43 - * @domain: IRQ domain for this instance 44 - */ 45 - struct gemini_irq_data { 46 - void __iomem *base; 47 - struct irq_chip chip; 48 - struct irq_domain *domain; 49 - }; 50 - 51 - static void gemini_irq_mask(struct irq_data *d) 52 - { 53 - struct gemini_irq_data *g = irq_data_get_irq_chip_data(d); 54 - unsigned int mask; 55 - 56 - mask = readl(GEMINI_IRQ_MASK(g->base)); 57 - mask &= ~BIT(irqd_to_hwirq(d)); 58 - writel(mask, GEMINI_IRQ_MASK(g->base)); 59 - } 60 - 61 - static void gemini_irq_unmask(struct irq_data *d) 62 - { 63 - struct gemini_irq_data *g = irq_data_get_irq_chip_data(d); 64 - unsigned int mask; 65 - 66 - mask = readl(GEMINI_IRQ_MASK(g->base)); 67 - mask |= BIT(irqd_to_hwirq(d)); 68 - writel(mask, GEMINI_IRQ_MASK(g->base)); 69 - } 70 - 71 - static void gemini_irq_ack(struct irq_data *d) 72 - { 73 - struct gemini_irq_data *g = irq_data_get_irq_chip_data(d); 74 - 75 - writel(BIT(irqd_to_hwirq(d)), GEMINI_IRQ_CLEAR(g->base)); 76 - } 77 - 78 - static int gemini_irq_set_type(struct irq_data *d, unsigned int trigger) 79 - { 80 - struct gemini_irq_data *g = irq_data_get_irq_chip_data(d); 81 - int offset = irqd_to_hwirq(d); 82 - u32 mode, polarity; 83 - 84 - mode = readl(GEMINI_IRQ_MODE(g->base)); 85 - polarity = readl(GEMINI_IRQ_POLARITY(g->base)); 86 - 87 - if (trigger & (IRQ_TYPE_LEVEL_HIGH)) { 88 - irq_set_handler_locked(d, handle_level_irq); 89 - /* Disable edge detection */ 90 - mode &= ~BIT(offset); 91 - polarity &= ~BIT(offset); 92 - } else if (trigger & IRQ_TYPE_EDGE_RISING) { 93 - irq_set_handler_locked(d, handle_edge_irq); 94 - mode |= BIT(offset); 95 - polarity |= BIT(offset); 96 - } else if (trigger & IRQ_TYPE_EDGE_FALLING) { 97 - irq_set_handler_locked(d, handle_edge_irq); 98 - mode |= BIT(offset); 99 - polarity &= ~BIT(offset); 100 - } else { 101 - irq_set_handler_locked(d, handle_bad_irq); 102 - pr_warn("GEMINI IRQ: no supported trigger selected for line %d\n", 103 - offset); 104 - } 105 - 106 - writel(mode, GEMINI_IRQ_MODE(g->base)); 107 - writel(polarity, GEMINI_IRQ_POLARITY(g->base)); 108 - 109 - return 0; 110 - } 111 - 112 - static struct irq_chip gemini_irq_chip = { 113 - .name = "GEMINI", 114 - .irq_ack = gemini_irq_ack, 115 - .irq_mask = gemini_irq_mask, 116 - .irq_unmask = gemini_irq_unmask, 117 - .irq_set_type = gemini_irq_set_type, 118 - }; 119 - 120 - /* Local static for the IRQ entry call */ 121 - static struct gemini_irq_data girq; 122 - 123 - asmlinkage void __exception_irq_entry gemini_irqchip_handle_irq(struct pt_regs *regs) 124 - { 125 - struct gemini_irq_data *g = &girq; 126 - int irq; 127 - u32 status; 128 - 129 - while ((status = readl(GEMINI_IRQ_STATUS(g->base)))) { 130 - irq = ffs(status) - 1; 131 - handle_domain_irq(g->domain, irq, regs); 132 - } 133 - } 134 - 135 - static int gemini_irqdomain_map(struct irq_domain *d, unsigned int irq, 136 - irq_hw_number_t hwirq) 137 - { 138 - struct gemini_irq_data *g = d->host_data; 139 - 140 - irq_set_chip_data(irq, g); 141 - /* All IRQs should set up their type, flags as bad by default */ 142 - irq_set_chip_and_handler(irq, &gemini_irq_chip, handle_bad_irq); 143 - irq_set_probe(irq); 144 - 145 - return 0; 146 - } 147 - 148 - static void gemini_irqdomain_unmap(struct irq_domain *d, unsigned int irq) 149 - { 150 - irq_set_chip_and_handler(irq, NULL, NULL); 151 - irq_set_chip_data(irq, NULL); 152 - } 153 - 154 - static const struct irq_domain_ops gemini_irqdomain_ops = { 155 - .map = gemini_irqdomain_map, 156 - .unmap = gemini_irqdomain_unmap, 157 - .xlate = irq_domain_xlate_onetwocell, 158 - }; 159 - 160 - int __init gemini_of_init_irq(struct device_node *node, 161 - struct device_node *parent) 162 - { 163 - struct gemini_irq_data *g = &girq; 164 - 165 - /* 166 - * Disable the idle handler by default since it is buggy 167 - * For more info see arch/arm/mach-gemini/idle.c 168 - */ 169 - cpu_idle_poll_ctrl(true); 170 - 171 - g->base = of_iomap(node, 0); 172 - WARN(!g->base, "unable to map gemini irq registers\n"); 173 - 174 - /* Disable all interrupts */ 175 - writel(0, GEMINI_IRQ_MASK(g->base)); 176 - writel(0, GEMINI_FIQ_MASK(g->base)); 177 - 178 - g->domain = irq_domain_add_simple(node, GEMINI_NUM_IRQS, 0, 179 - &gemini_irqdomain_ops, g); 180 - set_handle_irq(gemini_irqchip_handle_irq); 181 - 182 - return 0; 183 - } 184 - IRQCHIP_DECLARE(gemini, "cortina,gemini-interrupt-controller", 185 - gemini_of_init_irq);
+88 -25
drivers/irqchip/irq-gic-v3-its-platform-msi.c
··· 15 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 16 */ 17 17 18 + #include <linux/acpi_iort.h> 18 19 #include <linux/device.h> 19 20 #include <linux/msi.h> 20 21 #include <linux/of.h> ··· 25 24 .name = "ITS-pMSI", 26 25 }; 27 26 28 - static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev, 29 - int nvec, msi_alloc_info_t *info) 27 + static int of_pmsi_get_dev_id(struct irq_domain *domain, struct device *dev, 28 + u32 *dev_id) 30 29 { 31 - struct msi_domain_info *msi_info; 32 - u32 dev_id; 33 30 int ret, index = 0; 34 - 35 - msi_info = msi_get_domain_info(domain->parent); 36 31 37 32 /* Suck the DeviceID out of the msi-parent property */ 38 33 do { ··· 40 43 if (args.np == irq_domain_get_of_node(domain)) { 41 44 if (WARN_ON(args.args_count != 1)) 42 45 return -EINVAL; 43 - dev_id = args.args[0]; 46 + *dev_id = args.args[0]; 44 47 break; 45 48 } 46 49 } while (!ret); 47 50 51 + return ret; 52 + } 53 + 54 + int __weak iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id) 55 + { 56 + return -1; 57 + } 58 + 59 + static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev, 60 + int nvec, msi_alloc_info_t *info) 61 + { 62 + struct msi_domain_info *msi_info; 63 + u32 dev_id; 64 + int ret; 65 + 66 + msi_info = msi_get_domain_info(domain->parent); 67 + 68 + if (dev->of_node) 69 + ret = of_pmsi_get_dev_id(domain, dev, &dev_id); 70 + else 71 + ret = iort_pmsi_get_dev_id(dev, &dev_id); 48 72 if (ret) 49 73 return ret; 50 74 ··· 91 73 {}, 92 74 }; 93 75 94 - static int __init its_pmsi_init(void) 76 + static int __init its_pmsi_init_one(struct fwnode_handle *fwnode, 77 + const char *name) 78 + { 79 + struct irq_domain *parent; 80 + 81 + parent = irq_find_matching_fwnode(fwnode, DOMAIN_BUS_NEXUS); 82 + if (!parent || !msi_get_domain_info(parent)) { 83 + pr_err("%s: unable to locate ITS domain\n", name); 84 + return -ENXIO; 85 + } 86 + 87 + if (!platform_msi_create_irq_domain(fwnode, &its_pmsi_domain_info, 88 + parent)) { 89 + pr_err("%s: unable to create platform domain\n", name); 90 + return -ENXIO; 91 + } 92 + 93 + pr_info("Platform MSI: %s domain created\n", name); 94 + return 0; 95 + } 96 + 97 + #ifdef CONFIG_ACPI 98 + static int __init 99 + its_pmsi_parse_madt(struct acpi_subtable_header *header, 100 + const unsigned long end) 101 + { 102 + struct acpi_madt_generic_translator *its_entry; 103 + struct fwnode_handle *domain_handle; 104 + const char *node_name; 105 + int err = -ENXIO; 106 + 107 + its_entry = (struct acpi_madt_generic_translator *)header; 108 + node_name = kasprintf(GFP_KERNEL, "ITS@0x%lx", 109 + (long)its_entry->base_address); 110 + domain_handle = iort_find_domain_token(its_entry->translation_id); 111 + if (!domain_handle) { 112 + pr_err("%s: Unable to locate ITS domain handle\n", node_name); 113 + goto out; 114 + } 115 + 116 + err = its_pmsi_init_one(domain_handle, node_name); 117 + 118 + out: 119 + kfree(node_name); 120 + return err; 121 + } 122 + 123 + static void __init its_pmsi_acpi_init(void) 124 + { 125 + acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_TRANSLATOR, 126 + its_pmsi_parse_madt, 0); 127 + } 128 + #else 129 + static inline void its_pmsi_acpi_init(void) { } 130 + #endif 131 + 132 + static void __init its_pmsi_of_init(void) 95 133 { 96 134 struct device_node *np; 97 - struct irq_domain *parent; 98 135 99 136 for (np = of_find_matching_node(NULL, its_device_id); np; 100 137 np = of_find_matching_node(np, its_device_id)) { 101 138 if (!of_property_read_bool(np, "msi-controller")) 102 139 continue; 103 140 104 - parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS); 105 - if (!parent || !msi_get_domain_info(parent)) { 106 - pr_err("%s: unable to locate ITS domain\n", 107 - np->full_name); 108 - continue; 109 - } 110 - 111 - if (!platform_msi_create_irq_domain(of_node_to_fwnode(np), 112 - &its_pmsi_domain_info, 113 - parent)) { 114 - pr_err("%s: unable to create platform domain\n", 115 - np->full_name); 116 - continue; 117 - } 118 - 119 - pr_info("Platform MSI: %s domain created\n", np->full_name); 141 + its_pmsi_init_one(of_node_to_fwnode(np), np->full_name); 120 142 } 143 + } 121 144 145 + static int __init its_pmsi_init(void) 146 + { 147 + its_pmsi_of_init(); 148 + its_pmsi_acpi_init(); 122 149 return 0; 123 150 } 124 151 early_initcall(its_pmsi_init);
+1 -1
drivers/irqchip/irq-gic-v3-its.c
··· 16 16 */ 17 17 18 18 #include <linux/acpi.h> 19 + #include <linux/acpi_iort.h> 19 20 #include <linux/bitmap.h> 20 21 #include <linux/cpu.h> 21 22 #include <linux/delay.h> 22 23 #include <linux/dma-iommu.h> 23 24 #include <linux/interrupt.h> 24 25 #include <linux/irqdomain.h> 25 - #include <linux/acpi_iort.h> 26 26 #include <linux/log2.h> 27 27 #include <linux/mm.h> 28 28 #include <linux/msi.h>
+5
drivers/irqchip/irq-imx-gpcv2.c
··· 268 268 imx_gpcv2_instance = cd; 269 269 register_syscore_ops(&imx_gpcv2_syscore_ops); 270 270 271 + /* 272 + * Clear the OF_POPULATED flag set in of_irq_init so that 273 + * later the GPC power domain driver will not be skipped. 274 + */ 275 + of_node_clear_flag(node, OF_POPULATED); 271 276 return 0; 272 277 } 273 278
+97 -17
drivers/irqchip/irq-mbigen.c
··· 16 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 17 */ 18 18 19 + #include <linux/acpi.h> 19 20 #include <linux/interrupt.h> 20 21 #include <linux/irqchip.h> 21 22 #include <linux/module.h> ··· 181 180 unsigned long *hwirq, 182 181 unsigned int *type) 183 182 { 184 - if (is_of_node(fwspec->fwnode)) { 183 + if (is_of_node(fwspec->fwnode) || is_acpi_device_node(fwspec->fwnode)) { 185 184 if (fwspec->param_count != 2) 186 185 return -EINVAL; 187 186 ··· 237 236 .free = irq_domain_free_irqs_common, 238 237 }; 239 238 240 - static int mbigen_device_probe(struct platform_device *pdev) 239 + static int mbigen_of_create_domain(struct platform_device *pdev, 240 + struct mbigen_device *mgn_chip) 241 241 { 242 - struct mbigen_device *mgn_chip; 242 + struct device *parent; 243 243 struct platform_device *child; 244 244 struct irq_domain *domain; 245 245 struct device_node *np; 246 - struct device *parent; 247 - struct resource *res; 248 246 u32 num_pins; 249 - 250 - mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL); 251 - if (!mgn_chip) 252 - return -ENOMEM; 253 - 254 - mgn_chip->pdev = pdev; 255 - 256 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 257 - mgn_chip->base = devm_ioremap_resource(&pdev->dev, res); 258 - if (IS_ERR(mgn_chip->base)) 259 - return PTR_ERR(mgn_chip->base); 260 247 261 248 for_each_child_of_node(pdev->dev.of_node, np) { 262 249 if (!of_property_read_bool(np, "interrupt-controller")) ··· 269 280 return -ENOMEM; 270 281 } 271 282 283 + return 0; 284 + } 285 + 286 + #ifdef CONFIG_ACPI 287 + static int mbigen_acpi_create_domain(struct platform_device *pdev, 288 + struct mbigen_device *mgn_chip) 289 + { 290 + struct irq_domain *domain; 291 + u32 num_pins = 0; 292 + int ret; 293 + 294 + /* 295 + * "num-pins" is the total number of interrupt pins implemented in 296 + * this mbigen instance, and mbigen is an interrupt controller 297 + * connected to ITS converting wired interrupts into MSI, so we 298 + * use "num-pins" to alloc MSI vectors which are needed by client 299 + * devices connected to it. 300 + * 301 + * Here is the DSDT device node used for mbigen in firmware: 302 + * Device(MBI0) { 303 + * Name(_HID, "HISI0152") 304 + * Name(_UID, Zero) 305 + * Name(_CRS, ResourceTemplate() { 306 + * Memory32Fixed(ReadWrite, 0xa0080000, 0x10000) 307 + * }) 308 + * 309 + * Name(_DSD, Package () { 310 + * ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 311 + * Package () { 312 + * Package () {"num-pins", 378} 313 + * } 314 + * }) 315 + * } 316 + */ 317 + ret = device_property_read_u32(&pdev->dev, "num-pins", &num_pins); 318 + if (ret || num_pins == 0) 319 + return -EINVAL; 320 + 321 + domain = platform_msi_create_device_domain(&pdev->dev, num_pins, 322 + mbigen_write_msg, 323 + &mbigen_domain_ops, 324 + mgn_chip); 325 + if (!domain) 326 + return -ENOMEM; 327 + 328 + return 0; 329 + } 330 + #else 331 + static inline int mbigen_acpi_create_domain(struct platform_device *pdev, 332 + struct mbigen_device *mgn_chip) 333 + { 334 + return -ENODEV; 335 + } 336 + #endif 337 + 338 + static int mbigen_device_probe(struct platform_device *pdev) 339 + { 340 + struct mbigen_device *mgn_chip; 341 + struct resource *res; 342 + int err; 343 + 344 + mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL); 345 + if (!mgn_chip) 346 + return -ENOMEM; 347 + 348 + mgn_chip->pdev = pdev; 349 + 350 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 351 + mgn_chip->base = devm_ioremap_resource(&pdev->dev, res); 352 + if (IS_ERR(mgn_chip->base)) 353 + return PTR_ERR(mgn_chip->base); 354 + 355 + if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) 356 + err = mbigen_of_create_domain(pdev, mgn_chip); 357 + else if (ACPI_COMPANION(&pdev->dev)) 358 + err = mbigen_acpi_create_domain(pdev, mgn_chip); 359 + else 360 + err = -EINVAL; 361 + 362 + if (err) { 363 + dev_err(&pdev->dev, "Failed to create mbi-gen@%p irqdomain", 364 + mgn_chip->base); 365 + return err; 366 + } 367 + 272 368 platform_set_drvdata(pdev, mgn_chip); 273 369 return 0; 274 370 } ··· 364 290 }; 365 291 MODULE_DEVICE_TABLE(of, mbigen_of_match); 366 292 293 + static const struct acpi_device_id mbigen_acpi_match[] = { 294 + { "HISI0152", 0 }, 295 + {} 296 + }; 297 + MODULE_DEVICE_TABLE(acpi, mbigen_acpi_match); 298 + 367 299 static struct platform_driver mbigen_platform_driver = { 368 300 .driver = { 369 301 .name = "Hisilicon MBIGEN-V2", 370 - .owner = THIS_MODULE, 371 302 .of_match_table = mbigen_of_match, 303 + .acpi_match_table = ACPI_PTR(mbigen_acpi_match), 372 304 }, 373 305 .probe = mbigen_device_probe, 374 306 };
+106 -232
drivers/irqchip/irq-mips-gic.c
··· 29 29 DECLARE_BITMAP(pcpu_mask, GIC_MAX_INTRS); 30 30 }; 31 31 32 - struct gic_irq_spec { 33 - enum { 34 - GIC_DEVICE, 35 - GIC_IPI 36 - } type; 37 - 38 - union { 39 - struct cpumask *ipimask; 40 - unsigned int hwirq; 41 - }; 42 - }; 43 - 44 32 static unsigned long __gic_base_addr; 45 33 46 34 static void __iomem *gic_base; 47 35 static struct gic_pcpu_mask pcpu_masks[NR_CPUS]; 48 36 static DEFINE_SPINLOCK(gic_lock); 49 37 static struct irq_domain *gic_irq_domain; 50 - static struct irq_domain *gic_dev_domain; 51 38 static struct irq_domain *gic_ipi_domain; 52 39 static int gic_shared_intrs; 53 40 static int gic_vpes; ··· 42 55 static unsigned int timer_cpu_pin; 43 56 static struct irq_chip gic_level_irq_controller, gic_edge_irq_controller; 44 57 DECLARE_BITMAP(ipi_resrv, GIC_MAX_INTRS); 58 + DECLARE_BITMAP(ipi_available, GIC_MAX_INTRS); 45 59 46 60 static void __gic_irq_dispatch(void); 47 61 ··· 681 693 return 0; 682 694 } 683 695 684 - static int gic_setup_dev_chip(struct irq_domain *d, unsigned int virq, 685 - unsigned int hwirq) 686 - { 687 - struct irq_chip *chip; 688 - int err; 689 - 690 - if (hwirq >= GIC_SHARED_HWIRQ_BASE) { 691 - err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 692 - &gic_level_irq_controller, 693 - NULL); 694 - } else { 695 - switch (GIC_HWIRQ_TO_LOCAL(hwirq)) { 696 - case GIC_LOCAL_INT_TIMER: 697 - case GIC_LOCAL_INT_PERFCTR: 698 - case GIC_LOCAL_INT_FDC: 699 - /* 700 - * HACK: These are all really percpu interrupts, but 701 - * the rest of the MIPS kernel code does not use the 702 - * percpu IRQ API for them. 703 - */ 704 - chip = &gic_all_vpes_local_irq_controller; 705 - irq_set_handler(virq, handle_percpu_irq); 706 - break; 707 - 708 - default: 709 - chip = &gic_local_irq_controller; 710 - irq_set_handler(virq, handle_percpu_devid_irq); 711 - irq_set_percpu_devid(virq); 712 - break; 713 - } 714 - 715 - err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 716 - chip, NULL); 717 - } 718 - 719 - return err; 720 - } 721 - 722 - static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, 723 - unsigned int nr_irqs, void *arg) 724 - { 725 - struct gic_irq_spec *spec = arg; 726 - irq_hw_number_t hwirq, base_hwirq; 727 - int cpu, ret, i; 728 - 729 - if (spec->type == GIC_DEVICE) { 730 - /* verify that shared irqs don't conflict with an IPI irq */ 731 - if ((spec->hwirq >= GIC_SHARED_HWIRQ_BASE) && 732 - test_bit(GIC_HWIRQ_TO_SHARED(spec->hwirq), ipi_resrv)) 733 - return -EBUSY; 734 - 735 - return gic_setup_dev_chip(d, virq, spec->hwirq); 736 - } else { 737 - base_hwirq = find_first_bit(ipi_resrv, gic_shared_intrs); 738 - if (base_hwirq == gic_shared_intrs) { 739 - return -ENOMEM; 740 - } 741 - 742 - /* check that we have enough space */ 743 - for (i = base_hwirq; i < nr_irqs; i++) { 744 - if (!test_bit(i, ipi_resrv)) 745 - return -EBUSY; 746 - } 747 - bitmap_clear(ipi_resrv, base_hwirq, nr_irqs); 748 - 749 - /* map the hwirq for each cpu consecutively */ 750 - i = 0; 751 - for_each_cpu(cpu, spec->ipimask) { 752 - hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); 753 - 754 - ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, 755 - &gic_level_irq_controller, 756 - NULL); 757 - if (ret) 758 - goto error; 759 - 760 - irq_set_handler(virq + i, handle_level_irq); 761 - 762 - ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); 763 - if (ret) 764 - goto error; 765 - 766 - i++; 767 - } 768 - 769 - /* 770 - * tell the parent about the base hwirq we allocated so it can 771 - * set its own domain data 772 - */ 773 - spec->hwirq = base_hwirq; 774 - } 775 - 776 - return 0; 777 - error: 778 - bitmap_set(ipi_resrv, base_hwirq, nr_irqs); 779 - return ret; 780 - } 781 - 782 - void gic_irq_domain_free(struct irq_domain *d, unsigned int virq, 783 - unsigned int nr_irqs) 784 - { 785 - irq_hw_number_t base_hwirq; 786 - struct irq_data *data; 787 - 788 - data = irq_get_irq_data(virq); 789 - if (!data) 790 - return; 791 - 792 - base_hwirq = GIC_HWIRQ_TO_SHARED(irqd_to_hwirq(data)); 793 - bitmap_set(ipi_resrv, base_hwirq, nr_irqs); 794 - } 795 - 796 - int gic_irq_domain_match(struct irq_domain *d, struct device_node *node, 797 - enum irq_domain_bus_token bus_token) 798 - { 799 - /* this domain should'nt be accessed directly */ 800 - return 0; 801 - } 802 - 803 - static const struct irq_domain_ops gic_irq_domain_ops = { 804 - .alloc = gic_irq_domain_alloc, 805 - .free = gic_irq_domain_free, 806 - .match = gic_irq_domain_match, 807 - }; 808 - 809 - static int gic_dev_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, 696 + static int gic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, 810 697 const u32 *intspec, unsigned int intsize, 811 698 irq_hw_number_t *out_hwirq, 812 699 unsigned int *out_type) ··· 700 837 return 0; 701 838 } 702 839 703 - static int gic_dev_domain_alloc(struct irq_domain *d, unsigned int virq, 840 + static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, 841 + irq_hw_number_t hwirq) 842 + { 843 + int err; 844 + 845 + if (hwirq >= GIC_SHARED_HWIRQ_BASE) { 846 + /* verify that shared irqs don't conflict with an IPI irq */ 847 + if (test_bit(GIC_HWIRQ_TO_SHARED(hwirq), ipi_resrv)) 848 + return -EBUSY; 849 + 850 + err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 851 + &gic_level_irq_controller, 852 + NULL); 853 + if (err) 854 + return err; 855 + 856 + return gic_shared_irq_domain_map(d, virq, hwirq, 0); 857 + } 858 + 859 + switch (GIC_HWIRQ_TO_LOCAL(hwirq)) { 860 + case GIC_LOCAL_INT_TIMER: 861 + case GIC_LOCAL_INT_PERFCTR: 862 + case GIC_LOCAL_INT_FDC: 863 + /* 864 + * HACK: These are all really percpu interrupts, but 865 + * the rest of the MIPS kernel code does not use the 866 + * percpu IRQ API for them. 867 + */ 868 + err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 869 + &gic_all_vpes_local_irq_controller, 870 + NULL); 871 + if (err) 872 + return err; 873 + 874 + irq_set_handler(virq, handle_percpu_irq); 875 + break; 876 + 877 + default: 878 + err = irq_domain_set_hwirq_and_chip(d, virq, hwirq, 879 + &gic_local_irq_controller, 880 + NULL); 881 + if (err) 882 + return err; 883 + 884 + irq_set_handler(virq, handle_percpu_devid_irq); 885 + irq_set_percpu_devid(virq); 886 + break; 887 + } 888 + 889 + return gic_local_irq_domain_map(d, virq, hwirq); 890 + } 891 + 892 + static int gic_irq_domain_alloc(struct irq_domain *d, unsigned int virq, 704 893 unsigned int nr_irqs, void *arg) 705 894 { 706 895 struct irq_fwspec *fwspec = arg; 707 - struct gic_irq_spec spec = { 708 - .type = GIC_DEVICE, 709 - }; 710 - int i, ret; 896 + irq_hw_number_t hwirq; 711 897 712 898 if (fwspec->param[0] == GIC_SHARED) 713 - spec.hwirq = GIC_SHARED_TO_HWIRQ(fwspec->param[1]); 899 + hwirq = GIC_SHARED_TO_HWIRQ(fwspec->param[1]); 714 900 else 715 - spec.hwirq = GIC_LOCAL_TO_HWIRQ(fwspec->param[1]); 901 + hwirq = GIC_LOCAL_TO_HWIRQ(fwspec->param[1]); 716 902 717 - ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &spec); 718 - if (ret) 719 - return ret; 720 - 721 - for (i = 0; i < nr_irqs; i++) { 722 - ret = gic_setup_dev_chip(d, virq + i, spec.hwirq + i); 723 - if (ret) 724 - goto error; 725 - } 726 - 727 - return 0; 728 - 729 - error: 730 - irq_domain_free_irqs_parent(d, virq, nr_irqs); 731 - return ret; 903 + return gic_irq_domain_map(d, virq, hwirq); 732 904 } 733 905 734 - void gic_dev_domain_free(struct irq_domain *d, unsigned int virq, 906 + void gic_irq_domain_free(struct irq_domain *d, unsigned int virq, 735 907 unsigned int nr_irqs) 736 908 { 737 - /* no real allocation is done for dev irqs, so no need to free anything */ 738 - return; 739 909 } 740 910 741 - static void gic_dev_domain_activate(struct irq_domain *domain, 742 - struct irq_data *d) 743 - { 744 - if (GIC_HWIRQ_TO_LOCAL(d->hwirq) < GIC_NUM_LOCAL_INTRS) 745 - gic_local_irq_domain_map(domain, d->irq, d->hwirq); 746 - else 747 - gic_shared_irq_domain_map(domain, d->irq, d->hwirq, 0); 748 - } 749 - 750 - static struct irq_domain_ops gic_dev_domain_ops = { 751 - .xlate = gic_dev_domain_xlate, 752 - .alloc = gic_dev_domain_alloc, 753 - .free = gic_dev_domain_free, 754 - .activate = gic_dev_domain_activate, 911 + static const struct irq_domain_ops gic_irq_domain_ops = { 912 + .xlate = gic_irq_domain_xlate, 913 + .alloc = gic_irq_domain_alloc, 914 + .free = gic_irq_domain_free, 915 + .map = gic_irq_domain_map, 755 916 }; 756 917 757 918 static int gic_ipi_domain_xlate(struct irq_domain *d, struct device_node *ctrlr, ··· 797 910 unsigned int nr_irqs, void *arg) 798 911 { 799 912 struct cpumask *ipimask = arg; 800 - struct gic_irq_spec spec = { 801 - .type = GIC_IPI, 802 - .ipimask = ipimask 803 - }; 804 - int ret, i; 913 + irq_hw_number_t hwirq, base_hwirq; 914 + int cpu, ret, i; 805 915 806 - ret = irq_domain_alloc_irqs_parent(d, virq, nr_irqs, &spec); 807 - if (ret) 808 - return ret; 916 + base_hwirq = find_first_bit(ipi_available, gic_shared_intrs); 917 + if (base_hwirq == gic_shared_intrs) 918 + return -ENOMEM; 809 919 810 - /* the parent should have set spec.hwirq to the base_hwirq it allocated */ 811 - for (i = 0; i < nr_irqs; i++) { 812 - ret = irq_domain_set_hwirq_and_chip(d, virq + i, 813 - GIC_SHARED_TO_HWIRQ(spec.hwirq + i), 920 + /* check that we have enough space */ 921 + for (i = base_hwirq; i < nr_irqs; i++) { 922 + if (!test_bit(i, ipi_available)) 923 + return -EBUSY; 924 + } 925 + bitmap_clear(ipi_available, base_hwirq, nr_irqs); 926 + 927 + /* map the hwirq for each cpu consecutively */ 928 + i = 0; 929 + for_each_cpu(cpu, ipimask) { 930 + hwirq = GIC_SHARED_TO_HWIRQ(base_hwirq + i); 931 + 932 + ret = irq_domain_set_hwirq_and_chip(d, virq + i, hwirq, 933 + &gic_edge_irq_controller, 934 + NULL); 935 + if (ret) 936 + goto error; 937 + 938 + ret = irq_domain_set_hwirq_and_chip(d->parent, virq + i, hwirq, 814 939 &gic_edge_irq_controller, 815 940 NULL); 816 941 if (ret) ··· 831 932 ret = irq_set_irq_type(virq + i, IRQ_TYPE_EDGE_RISING); 832 933 if (ret) 833 934 goto error; 935 + 936 + ret = gic_shared_irq_domain_map(d, virq + i, hwirq, cpu); 937 + if (ret) 938 + goto error; 939 + 940 + i++; 834 941 } 835 942 836 943 return 0; 837 944 error: 838 - irq_domain_free_irqs_parent(d, virq, nr_irqs); 945 + bitmap_set(ipi_available, base_hwirq, nr_irqs); 839 946 return ret; 840 947 } 841 948 842 949 void gic_ipi_domain_free(struct irq_domain *d, unsigned int virq, 843 950 unsigned int nr_irqs) 844 951 { 845 - irq_domain_free_irqs_parent(d, virq, nr_irqs); 952 + irq_hw_number_t base_hwirq; 953 + struct irq_data *data; 954 + 955 + data = irq_get_irq_data(virq); 956 + if (!data) 957 + return; 958 + 959 + base_hwirq = GIC_HWIRQ_TO_SHARED(irqd_to_hwirq(data)); 960 + bitmap_set(ipi_available, base_hwirq, nr_irqs); 846 961 } 847 962 848 963 int gic_ipi_domain_match(struct irq_domain *d, struct device_node *node, ··· 880 967 .free = gic_ipi_domain_free, 881 968 .match = gic_ipi_domain_match, 882 969 }; 883 - 884 - static void __init gic_map_single_int(struct device_node *node, 885 - unsigned int irq) 886 - { 887 - unsigned int linux_irq; 888 - struct irq_fwspec local_int_fwspec = { 889 - .fwnode = &node->fwnode, 890 - .param_count = 3, 891 - .param = { 892 - [0] = GIC_LOCAL, 893 - [1] = irq, 894 - [2] = IRQ_TYPE_NONE, 895 - }, 896 - }; 897 - 898 - if (!gic_local_irq_is_routable(irq)) 899 - return; 900 - 901 - linux_irq = irq_create_fwspec_mapping(&local_int_fwspec); 902 - WARN_ON(!linux_irq); 903 - } 904 - 905 - static void __init gic_map_interrupts(struct device_node *node) 906 - { 907 - gic_map_single_int(node, GIC_LOCAL_INT_WD); 908 - gic_map_single_int(node, GIC_LOCAL_INT_COMPARE); 909 - gic_map_single_int(node, GIC_LOCAL_INT_TIMER); 910 - gic_map_single_int(node, GIC_LOCAL_INT_PERFCTR); 911 - gic_map_single_int(node, GIC_LOCAL_INT_SWINT0); 912 - gic_map_single_int(node, GIC_LOCAL_INT_SWINT1); 913 - gic_map_single_int(node, GIC_LOCAL_INT_FDC); 914 - } 915 970 916 971 static void __init __gic_init(unsigned long gic_base_addr, 917 972 unsigned long gic_addrspace_size, ··· 952 1071 panic("Failed to add GIC IRQ domain"); 953 1072 gic_irq_domain->name = "mips-gic-irq"; 954 1073 955 - gic_dev_domain = irq_domain_add_hierarchy(gic_irq_domain, 0, 956 - GIC_NUM_LOCAL_INTRS + gic_shared_intrs, 957 - node, &gic_dev_domain_ops, NULL); 958 - if (!gic_dev_domain) 959 - panic("Failed to add GIC DEV domain"); 960 - gic_dev_domain->name = "mips-gic-dev"; 961 - 962 1074 gic_ipi_domain = irq_domain_add_hierarchy(gic_irq_domain, 963 1075 IRQ_DOMAIN_FLAG_IPI_PER_CPU, 964 1076 GIC_NUM_LOCAL_INTRS + gic_shared_intrs, ··· 972 1098 2 * gic_vpes); 973 1099 } 974 1100 1101 + bitmap_copy(ipi_available, ipi_resrv, GIC_MAX_INTRS); 975 1102 gic_basic_init(); 976 - gic_map_interrupts(node); 977 1103 } 978 1104 979 1105 void __init gic_init(unsigned long gic_base_addr,
-116
drivers/irqchip/irq-moxart.c
··· 1 - /* 2 - * MOXA ART SoCs IRQ chip driver. 3 - * 4 - * Copyright (C) 2013 Jonas Jensen 5 - * 6 - * Jonas Jensen <jonas.jensen@gmail.com> 7 - * 8 - * This file is licensed under the terms of the GNU General Public 9 - * License version 2. This program is licensed "as is" without any 10 - * warranty of any kind, whether express or implied. 11 - */ 12 - 13 - #include <linux/io.h> 14 - #include <linux/irq.h> 15 - #include <linux/irqchip.h> 16 - #include <linux/of.h> 17 - #include <linux/of_address.h> 18 - #include <linux/of_irq.h> 19 - #include <linux/irqdomain.h> 20 - 21 - #include <asm/exception.h> 22 - 23 - #define IRQ_SOURCE_REG 0 24 - #define IRQ_MASK_REG 0x04 25 - #define IRQ_CLEAR_REG 0x08 26 - #define IRQ_MODE_REG 0x0c 27 - #define IRQ_LEVEL_REG 0x10 28 - #define IRQ_STATUS_REG 0x14 29 - 30 - #define FIQ_SOURCE_REG 0x20 31 - #define FIQ_MASK_REG 0x24 32 - #define FIQ_CLEAR_REG 0x28 33 - #define FIQ_MODE_REG 0x2c 34 - #define FIQ_LEVEL_REG 0x30 35 - #define FIQ_STATUS_REG 0x34 36 - 37 - 38 - struct moxart_irq_data { 39 - void __iomem *base; 40 - struct irq_domain *domain; 41 - unsigned int interrupt_mask; 42 - }; 43 - 44 - static struct moxart_irq_data intc; 45 - 46 - static void __exception_irq_entry handle_irq(struct pt_regs *regs) 47 - { 48 - u32 irqstat; 49 - int hwirq; 50 - 51 - irqstat = readl(intc.base + IRQ_STATUS_REG); 52 - 53 - while (irqstat) { 54 - hwirq = ffs(irqstat) - 1; 55 - handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs); 56 - irqstat &= ~(1 << hwirq); 57 - } 58 - } 59 - 60 - static int __init moxart_of_intc_init(struct device_node *node, 61 - struct device_node *parent) 62 - { 63 - unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN; 64 - int ret; 65 - struct irq_chip_generic *gc; 66 - 67 - intc.base = of_iomap(node, 0); 68 - if (!intc.base) { 69 - pr_err("%s: unable to map IC registers\n", 70 - node->full_name); 71 - return -EINVAL; 72 - } 73 - 74 - intc.domain = irq_domain_add_linear(node, 32, &irq_generic_chip_ops, 75 - intc.base); 76 - if (!intc.domain) { 77 - pr_err("%s: unable to create IRQ domain\n", node->full_name); 78 - return -EINVAL; 79 - } 80 - 81 - ret = irq_alloc_domain_generic_chips(intc.domain, 32, 1, 82 - "MOXARTINTC", handle_edge_irq, 83 - clr, 0, IRQ_GC_INIT_MASK_CACHE); 84 - if (ret) { 85 - pr_err("%s: could not allocate generic chip\n", 86 - node->full_name); 87 - irq_domain_remove(intc.domain); 88 - return -EINVAL; 89 - } 90 - 91 - ret = of_property_read_u32(node, "interrupt-mask", 92 - &intc.interrupt_mask); 93 - if (ret) 94 - pr_err("%s: could not read interrupt-mask DT property\n", 95 - node->full_name); 96 - 97 - gc = irq_get_domain_generic_chip(intc.domain, 0); 98 - 99 - gc->reg_base = intc.base; 100 - gc->chip_types[0].regs.mask = IRQ_MASK_REG; 101 - gc->chip_types[0].regs.ack = IRQ_CLEAR_REG; 102 - gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; 103 - gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; 104 - gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; 105 - 106 - writel(0, intc.base + IRQ_MASK_REG); 107 - writel(0xffffffff, intc.base + IRQ_CLEAR_REG); 108 - 109 - writel(intc.interrupt_mask, intc.base + IRQ_MODE_REG); 110 - writel(intc.interrupt_mask, intc.base + IRQ_LEVEL_REG); 111 - 112 - set_handle_irq(handle_irq); 113 - 114 - return 0; 115 - } 116 - IRQCHIP_DECLARE(moxa_moxart_ic, "moxa,moxart-ic", moxart_of_intc_init);
+306
drivers/irqchip/irq-mtk-cirq.c
··· 1 + /* 2 + * Copyright (c) 2016 MediaTek Inc. 3 + * Author: Youlin.Pei <youlin.pei@mediatek.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + */ 14 + 15 + #include <linux/interrupt.h> 16 + #include <linux/io.h> 17 + #include <linux/irq.h> 18 + #include <linux/irqchip.h> 19 + #include <linux/irqdomain.h> 20 + #include <linux/of.h> 21 + #include <linux/of_irq.h> 22 + #include <linux/of_address.h> 23 + #include <linux/slab.h> 24 + #include <linux/syscore_ops.h> 25 + 26 + #define CIRQ_ACK 0x40 27 + #define CIRQ_MASK_SET 0xc0 28 + #define CIRQ_MASK_CLR 0x100 29 + #define CIRQ_SENS_SET 0x180 30 + #define CIRQ_SENS_CLR 0x1c0 31 + #define CIRQ_POL_SET 0x240 32 + #define CIRQ_POL_CLR 0x280 33 + #define CIRQ_CONTROL 0x300 34 + 35 + #define CIRQ_EN 0x1 36 + #define CIRQ_EDGE 0x2 37 + #define CIRQ_FLUSH 0x4 38 + 39 + struct mtk_cirq_chip_data { 40 + void __iomem *base; 41 + unsigned int ext_irq_start; 42 + unsigned int ext_irq_end; 43 + struct irq_domain *domain; 44 + }; 45 + 46 + static struct mtk_cirq_chip_data *cirq_data; 47 + 48 + static void mtk_cirq_write_mask(struct irq_data *data, unsigned int offset) 49 + { 50 + struct mtk_cirq_chip_data *chip_data = data->chip_data; 51 + unsigned int cirq_num = data->hwirq; 52 + u32 mask = 1 << (cirq_num % 32); 53 + 54 + writel_relaxed(mask, chip_data->base + offset + (cirq_num / 32) * 4); 55 + } 56 + 57 + static void mtk_cirq_mask(struct irq_data *data) 58 + { 59 + mtk_cirq_write_mask(data, CIRQ_MASK_SET); 60 + irq_chip_mask_parent(data); 61 + } 62 + 63 + static void mtk_cirq_unmask(struct irq_data *data) 64 + { 65 + mtk_cirq_write_mask(data, CIRQ_MASK_CLR); 66 + irq_chip_unmask_parent(data); 67 + } 68 + 69 + static int mtk_cirq_set_type(struct irq_data *data, unsigned int type) 70 + { 71 + int ret; 72 + 73 + switch (type & IRQ_TYPE_SENSE_MASK) { 74 + case IRQ_TYPE_EDGE_FALLING: 75 + mtk_cirq_write_mask(data, CIRQ_POL_CLR); 76 + mtk_cirq_write_mask(data, CIRQ_SENS_CLR); 77 + break; 78 + case IRQ_TYPE_EDGE_RISING: 79 + mtk_cirq_write_mask(data, CIRQ_POL_SET); 80 + mtk_cirq_write_mask(data, CIRQ_SENS_CLR); 81 + break; 82 + case IRQ_TYPE_LEVEL_LOW: 83 + mtk_cirq_write_mask(data, CIRQ_POL_CLR); 84 + mtk_cirq_write_mask(data, CIRQ_SENS_SET); 85 + break; 86 + case IRQ_TYPE_LEVEL_HIGH: 87 + mtk_cirq_write_mask(data, CIRQ_POL_SET); 88 + mtk_cirq_write_mask(data, CIRQ_SENS_SET); 89 + break; 90 + default: 91 + break; 92 + } 93 + 94 + data = data->parent_data; 95 + ret = data->chip->irq_set_type(data, type); 96 + return ret; 97 + } 98 + 99 + static struct irq_chip mtk_cirq_chip = { 100 + .name = "MT_CIRQ", 101 + .irq_mask = mtk_cirq_mask, 102 + .irq_unmask = mtk_cirq_unmask, 103 + .irq_eoi = irq_chip_eoi_parent, 104 + .irq_set_type = mtk_cirq_set_type, 105 + .irq_retrigger = irq_chip_retrigger_hierarchy, 106 + #ifdef CONFIG_SMP 107 + .irq_set_affinity = irq_chip_set_affinity_parent, 108 + #endif 109 + }; 110 + 111 + static int mtk_cirq_domain_translate(struct irq_domain *d, 112 + struct irq_fwspec *fwspec, 113 + unsigned long *hwirq, 114 + unsigned int *type) 115 + { 116 + if (is_of_node(fwspec->fwnode)) { 117 + if (fwspec->param_count != 3) 118 + return -EINVAL; 119 + 120 + /* No PPI should point to this domain */ 121 + if (fwspec->param[0] != 0) 122 + return -EINVAL; 123 + 124 + /* cirq support irq number check */ 125 + if (fwspec->param[1] < cirq_data->ext_irq_start || 126 + fwspec->param[1] > cirq_data->ext_irq_end) 127 + return -EINVAL; 128 + 129 + *hwirq = fwspec->param[1] - cirq_data->ext_irq_start; 130 + *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; 131 + return 0; 132 + } 133 + 134 + return -EINVAL; 135 + } 136 + 137 + static int mtk_cirq_domain_alloc(struct irq_domain *domain, unsigned int virq, 138 + unsigned int nr_irqs, void *arg) 139 + { 140 + int ret; 141 + irq_hw_number_t hwirq; 142 + unsigned int type; 143 + struct irq_fwspec *fwspec = arg; 144 + struct irq_fwspec parent_fwspec = *fwspec; 145 + 146 + ret = mtk_cirq_domain_translate(domain, fwspec, &hwirq, &type); 147 + if (ret) 148 + return ret; 149 + 150 + if (WARN_ON(nr_irqs != 1)) 151 + return -EINVAL; 152 + 153 + irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 154 + &mtk_cirq_chip, 155 + domain->host_data); 156 + 157 + parent_fwspec.fwnode = domain->parent->fwnode; 158 + return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, 159 + &parent_fwspec); 160 + } 161 + 162 + static const struct irq_domain_ops cirq_domain_ops = { 163 + .translate = mtk_cirq_domain_translate, 164 + .alloc = mtk_cirq_domain_alloc, 165 + .free = irq_domain_free_irqs_common, 166 + }; 167 + 168 + #ifdef CONFIG_PM_SLEEP 169 + static int mtk_cirq_suspend(void) 170 + { 171 + u32 value, mask; 172 + unsigned int irq, hwirq_num; 173 + bool pending, masked; 174 + int i, pendret, maskret; 175 + 176 + /* 177 + * When external interrupts happened, CIRQ will record the status 178 + * even CIRQ is not enabled. When execute flush command, CIRQ will 179 + * resend the signals according to the status. So if don't clear the 180 + * status, CIRQ will resend the wrong signals. 181 + * 182 + * arch_suspend_disable_irqs() will be called before CIRQ suspend 183 + * callback. If clear all the status simply, the external interrupts 184 + * which happened between arch_suspend_disable_irqs and CIRQ suspend 185 + * callback will be lost. Using following steps to avoid this issue; 186 + * 187 + * - Iterate over all the CIRQ supported interrupts; 188 + * - For each interrupt, inspect its pending and masked status at GIC 189 + * level; 190 + * - If pending and unmasked, it happened between 191 + * arch_suspend_disable_irqs and CIRQ suspend callback, don't ACK 192 + * it. Otherwise, ACK it. 193 + */ 194 + hwirq_num = cirq_data->ext_irq_end - cirq_data->ext_irq_start + 1; 195 + for (i = 0; i < hwirq_num; i++) { 196 + irq = irq_find_mapping(cirq_data->domain, i); 197 + if (irq) { 198 + pendret = irq_get_irqchip_state(irq, 199 + IRQCHIP_STATE_PENDING, 200 + &pending); 201 + 202 + maskret = irq_get_irqchip_state(irq, 203 + IRQCHIP_STATE_MASKED, 204 + &masked); 205 + 206 + if (pendret == 0 && maskret == 0 && 207 + (pending && !masked)) 208 + continue; 209 + } 210 + 211 + mask = 1 << (i % 32); 212 + writel_relaxed(mask, cirq_data->base + CIRQ_ACK + (i / 32) * 4); 213 + } 214 + 215 + /* set edge_only mode, record edge-triggerd interrupts */ 216 + /* enable cirq */ 217 + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL); 218 + value |= (CIRQ_EDGE | CIRQ_EN); 219 + writel_relaxed(value, cirq_data->base + CIRQ_CONTROL); 220 + 221 + return 0; 222 + } 223 + 224 + static void mtk_cirq_resume(void) 225 + { 226 + u32 value; 227 + 228 + /* flush recored interrupts, will send signals to parent controller */ 229 + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL); 230 + writel_relaxed(value | CIRQ_FLUSH, cirq_data->base + CIRQ_CONTROL); 231 + 232 + /* disable cirq */ 233 + value = readl_relaxed(cirq_data->base + CIRQ_CONTROL); 234 + value &= ~(CIRQ_EDGE | CIRQ_EN); 235 + writel_relaxed(value, cirq_data->base + CIRQ_CONTROL); 236 + } 237 + 238 + static struct syscore_ops mtk_cirq_syscore_ops = { 239 + .suspend = mtk_cirq_suspend, 240 + .resume = mtk_cirq_resume, 241 + }; 242 + 243 + static void mtk_cirq_syscore_init(void) 244 + { 245 + register_syscore_ops(&mtk_cirq_syscore_ops); 246 + } 247 + #else 248 + static inline void mtk_cirq_syscore_init(void) {} 249 + #endif 250 + 251 + static int __init mtk_cirq_of_init(struct device_node *node, 252 + struct device_node *parent) 253 + { 254 + struct irq_domain *domain, *domain_parent; 255 + unsigned int irq_num; 256 + int ret; 257 + 258 + domain_parent = irq_find_host(parent); 259 + if (!domain_parent) { 260 + pr_err("mtk_cirq: interrupt-parent not found\n"); 261 + return -EINVAL; 262 + } 263 + 264 + cirq_data = kzalloc(sizeof(*cirq_data), GFP_KERNEL); 265 + if (!cirq_data) 266 + return -ENOMEM; 267 + 268 + cirq_data->base = of_iomap(node, 0); 269 + if (!cirq_data->base) { 270 + pr_err("mtk_cirq: unable to map cirq register\n"); 271 + ret = -ENXIO; 272 + goto out_free; 273 + } 274 + 275 + ret = of_property_read_u32_index(node, "mediatek,ext-irq-range", 0, 276 + &cirq_data->ext_irq_start); 277 + if (ret) 278 + goto out_unmap; 279 + 280 + ret = of_property_read_u32_index(node, "mediatek,ext-irq-range", 1, 281 + &cirq_data->ext_irq_end); 282 + if (ret) 283 + goto out_unmap; 284 + 285 + irq_num = cirq_data->ext_irq_end - cirq_data->ext_irq_start + 1; 286 + domain = irq_domain_add_hierarchy(domain_parent, 0, 287 + irq_num, node, 288 + &cirq_domain_ops, cirq_data); 289 + if (!domain) { 290 + ret = -ENOMEM; 291 + goto out_unmap; 292 + } 293 + cirq_data->domain = domain; 294 + 295 + mtk_cirq_syscore_init(); 296 + 297 + return 0; 298 + 299 + out_unmap: 300 + iounmap(cirq_data->base); 301 + out_free: 302 + kfree(cirq_data); 303 + return ret; 304 + } 305 + 306 + IRQCHIP_DECLARE(mtk_cirq, "mediatek,mtk-cirq", mtk_cirq_of_init);
+95 -21
drivers/irqchip/irq-mtk-sysirq.c
··· 24 24 25 25 struct mtk_sysirq_chip_data { 26 26 spinlock_t lock; 27 - void __iomem *intpol_base; 27 + u32 nr_intpol_bases; 28 + void __iomem **intpol_bases; 29 + u32 *intpol_words; 30 + u8 *intpol_idx; 31 + u16 *which_word; 28 32 }; 29 33 30 34 static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type) 31 35 { 32 36 irq_hw_number_t hwirq = data->hwirq; 33 37 struct mtk_sysirq_chip_data *chip_data = data->chip_data; 38 + u8 intpol_idx = chip_data->intpol_idx[hwirq]; 39 + void __iomem *base; 34 40 u32 offset, reg_index, value; 35 41 unsigned long flags; 36 42 int ret; 37 43 44 + base = chip_data->intpol_bases[intpol_idx]; 45 + reg_index = chip_data->which_word[hwirq]; 38 46 offset = hwirq & 0x1f; 39 - reg_index = hwirq >> 5; 40 47 41 48 spin_lock_irqsave(&chip_data->lock, flags); 42 - value = readl_relaxed(chip_data->intpol_base + reg_index * 4); 49 + value = readl_relaxed(base + reg_index * 4); 43 50 if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING) { 44 51 if (type == IRQ_TYPE_LEVEL_LOW) 45 52 type = IRQ_TYPE_LEVEL_HIGH; ··· 56 49 } else { 57 50 value &= ~(1 << offset); 58 51 } 59 - writel(value, chip_data->intpol_base + reg_index * 4); 52 + 53 + writel_relaxed(value, base + reg_index * 4); 60 54 61 55 data = data->parent_data; 62 56 ret = data->chip->irq_set_type(data, type); ··· 132 124 { 133 125 struct irq_domain *domain, *domain_parent; 134 126 struct mtk_sysirq_chip_data *chip_data; 135 - int ret, size, intpol_num; 136 - struct resource res; 127 + int ret, size, intpol_num = 0, nr_intpol_bases = 0, i = 0; 137 128 138 129 domain_parent = irq_find_host(parent); 139 130 if (!domain_parent) { ··· 140 133 return -EINVAL; 141 134 } 142 135 143 - ret = of_address_to_resource(node, 0, &res); 144 - if (ret) 145 - return ret; 146 - 147 136 chip_data = kzalloc(sizeof(*chip_data), GFP_KERNEL); 148 137 if (!chip_data) 149 138 return -ENOMEM; 150 139 151 - size = resource_size(&res); 152 - intpol_num = size * 8; 153 - chip_data->intpol_base = ioremap(res.start, size); 154 - if (!chip_data->intpol_base) { 155 - pr_err("mtk_sysirq: unable to map sysirq register\n"); 156 - ret = -ENXIO; 157 - goto out_free; 140 + while (of_get_address(node, i++, NULL, NULL)) 141 + nr_intpol_bases++; 142 + 143 + if (nr_intpol_bases == 0) { 144 + pr_err("mtk_sysirq: base address not specified\n"); 145 + ret = -EINVAL; 146 + goto out_free_chip; 147 + } 148 + 149 + chip_data->intpol_words = kcalloc(nr_intpol_bases, 150 + sizeof(*chip_data->intpol_words), 151 + GFP_KERNEL); 152 + if (!chip_data->intpol_words) { 153 + ret = -ENOMEM; 154 + goto out_free_chip; 155 + } 156 + 157 + chip_data->intpol_bases = kcalloc(nr_intpol_bases, 158 + sizeof(*chip_data->intpol_bases), 159 + GFP_KERNEL); 160 + if (!chip_data->intpol_bases) { 161 + ret = -ENOMEM; 162 + goto out_free_intpol_words; 163 + } 164 + 165 + for (i = 0; i < nr_intpol_bases; i++) { 166 + struct resource res; 167 + 168 + ret = of_address_to_resource(node, i, &res); 169 + size = resource_size(&res); 170 + intpol_num += size * 8; 171 + chip_data->intpol_words[i] = size / 4; 172 + chip_data->intpol_bases[i] = of_iomap(node, i); 173 + if (ret || !chip_data->intpol_bases[i]) { 174 + pr_err("%s: couldn't map region %d\n", 175 + node->full_name, i); 176 + ret = -ENODEV; 177 + goto out_free_intpol; 178 + } 179 + } 180 + 181 + chip_data->intpol_idx = kcalloc(intpol_num, 182 + sizeof(*chip_data->intpol_idx), 183 + GFP_KERNEL); 184 + if (!chip_data->intpol_idx) { 185 + ret = -ENOMEM; 186 + goto out_free_intpol; 187 + } 188 + 189 + chip_data->which_word = kcalloc(intpol_num, 190 + sizeof(*chip_data->which_word), 191 + GFP_KERNEL); 192 + if (!chip_data->which_word) { 193 + ret = -ENOMEM; 194 + goto out_free_intpol_idx; 195 + } 196 + 197 + /* 198 + * assign an index of the intpol_bases for each irq 199 + * to set it fast later 200 + */ 201 + for (i = 0; i < intpol_num ; i++) { 202 + u32 word = i / 32, j; 203 + 204 + for (j = 0; word >= chip_data->intpol_words[j] ; j++) 205 + word -= chip_data->intpol_words[j]; 206 + 207 + chip_data->intpol_idx[i] = j; 208 + chip_data->which_word[i] = word; 158 209 } 159 210 160 211 domain = irq_domain_add_hierarchy(domain_parent, 0, intpol_num, node, 161 212 &sysirq_domain_ops, chip_data); 162 213 if (!domain) { 163 214 ret = -ENOMEM; 164 - goto out_unmap; 215 + goto out_free_which_word; 165 216 } 166 217 spin_lock_init(&chip_data->lock); 167 218 168 219 return 0; 169 220 170 - out_unmap: 171 - iounmap(chip_data->intpol_base); 172 - out_free: 221 + out_free_which_word: 222 + kfree(chip_data->which_word); 223 + out_free_intpol_idx: 224 + kfree(chip_data->intpol_idx); 225 + out_free_intpol: 226 + for (i = 0; i < nr_intpol_bases; i++) 227 + if (chip_data->intpol_bases[i]) 228 + iounmap(chip_data->intpol_bases[i]); 229 + kfree(chip_data->intpol_bases); 230 + out_free_intpol_words: 231 + kfree(chip_data->intpol_words); 232 + out_free_chip: 173 233 kfree(chip_data); 174 234 return ret; 175 235 }
+10
include/linux/cpumask.h
··· 667 667 void free_cpumask_var(cpumask_var_t mask); 668 668 void free_bootmem_cpumask_var(cpumask_var_t mask); 669 669 670 + static inline bool cpumask_available(cpumask_var_t mask) 671 + { 672 + return mask != NULL; 673 + } 674 + 670 675 #else 671 676 typedef struct cpumask cpumask_var_t[1]; 672 677 ··· 712 707 713 708 static inline void free_bootmem_cpumask_var(cpumask_var_t mask) 714 709 { 710 + } 711 + 712 + static inline bool cpumask_available(cpumask_var_t mask) 713 + { 714 + return true; 715 715 } 716 716 #endif /* CONFIG_CPUMASK_OFFSTACK */ 717 717
+4 -1
kernel/irq/chip.c
··· 348 348 irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); 349 349 raw_spin_unlock_irq(&desc->lock); 350 350 351 - action_ret = action->thread_fn(action->irq, action->dev_id); 351 + action_ret = IRQ_NONE; 352 + for_each_action_of_desc(desc, action) 353 + action_ret |= action->thread_fn(action->irq, action->dev_id); 354 + 352 355 if (!noirqdebug) 353 356 note_interrupt(desc, action_ret); 354 357
+4 -2
kernel/irq/manage.c
··· 852 852 * This code is triggered unconditionally. Check the affinity 853 853 * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out. 854 854 */ 855 - if (desc->irq_common_data.affinity) 855 + if (cpumask_available(desc->irq_common_data.affinity)) 856 856 cpumask_copy(mask, desc->irq_common_data.affinity); 857 857 else 858 858 valid = false; ··· 1212 1212 * set the trigger type must match. Also all must 1213 1213 * agree on ONESHOT. 1214 1214 */ 1215 + unsigned int oldtype = irqd_get_trigger_type(&desc->irq_data); 1216 + 1215 1217 if (!((old->flags & new->flags) & IRQF_SHARED) || 1216 - ((old->flags ^ new->flags) & IRQF_TRIGGER_MASK) || 1218 + (oldtype != (new->flags & IRQF_TRIGGER_MASK)) || 1217 1219 ((old->flags ^ new->flags) & IRQF_ONESHOT)) 1218 1220 goto mismatch; 1219 1221