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

Merge tag 'irqchip-core-4.6-2' of git://git.infradead.org/users/jcooper/linux into irq/core

Pull the second round of irqchip core changes for v4.6 from Jason Cooper:

- mvebu:
- Add odmi driver for Marvell 7K/8K SoCs
- Replace driver-specific set_affinity with generic version

- mips:
- Move ath79 MISC and CPU drivers from arch/ code to irqchip/

- tango:
- Add support for Sigma Designs SMP8[67]xx ctrl

+884 -237
+41
Documentation/devicetree/bindings/interrupt-controller/marvell,odmi-controller.txt
··· 1 + 2 + * Marvell ODMI for MSI support 3 + 4 + Some Marvell SoCs have an On-Die Message Interrupt (ODMI) controller 5 + which can be used by on-board peripheral for MSI interrupts. 6 + 7 + Required properties: 8 + 9 + - compatible : The value here should contain "marvell,odmi-controller". 10 + 11 + - interrupt,controller : Identifies the node as an interrupt controller. 12 + 13 + - msi-controller : Identifies the node as an MSI controller. 14 + 15 + - marvell,odmi-frames : Number of ODMI frames available. Each frame 16 + provides a number of events. 17 + 18 + - reg : List of register definitions, one for each 19 + ODMI frame. 20 + 21 + - marvell,spi-base : List of GIC base SPI interrupts, one for each 22 + ODMI frame. Those SPI interrupts are 0-based, 23 + i.e marvell,spi-base = <128> will use SPI #96. 24 + See Documentation/devicetree/bindings/interrupt-controller/arm,gic.txt 25 + for details about the GIC Device Tree binding. 26 + 27 + - interrupt-parent : Reference to the parent interrupt controller. 28 + 29 + Example: 30 + 31 + odmi: odmi@300000 { 32 + compatible = "marvell,odmi-controller"; 33 + interrupt-controller; 34 + msi-controller; 35 + marvell,odmi-frames = <4>; 36 + reg = <0x300000 0x4000>, 37 + <0x304000 0x4000>, 38 + <0x308000 0x4000>, 39 + <0x30C000 0x4000>; 40 + marvell,spi-base = <128>, <136>, <144>, <152>; 41 + };
+49
Documentation/devicetree/bindings/interrupt-controller/sigma,smp8642-intc.txt
··· 1 + Sigma Designs SMP86xx/SMP87xx secondary interrupt controller 2 + 3 + Required properties: 4 + - compatible: should be "sigma,smp8642-intc" 5 + - reg: physical address of MMIO region 6 + - ranges: address space mapping of child nodes 7 + - interrupt-parent: phandle of parent interrupt controller 8 + - interrupt-controller: boolean 9 + - #address-cells: should be <1> 10 + - #size-cells: should be <1> 11 + 12 + One child node per control block with properties: 13 + - reg: address of registers for this control block 14 + - interrupt-controller: boolean 15 + - #interrupt-cells: should be <2>, interrupt index and flags per interrupts.txt 16 + - interrupts: interrupt spec of primary interrupt controller 17 + 18 + Example: 19 + 20 + interrupt-controller@6e000 { 21 + compatible = "sigma,smp8642-intc"; 22 + reg = <0x6e000 0x400>; 23 + ranges = <0x0 0x6e000 0x400>; 24 + interrupt-parent = <&gic>; 25 + interrupt-controller; 26 + #address-cells = <1>; 27 + #size-cells = <1>; 28 + 29 + irq0: interrupt-controller@0 { 30 + reg = <0x000 0x100>; 31 + interrupt-controller; 32 + #interrupt-cells = <2>; 33 + interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; 34 + }; 35 + 36 + irq1: interrupt-controller@100 { 37 + reg = <0x100 0x100>; 38 + interrupt-controller; 39 + #interrupt-cells = <2>; 40 + interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>; 41 + }; 42 + 43 + irq2: interrupt-controller@300 { 44 + reg = <0x300 0x100>; 45 + interrupt-controller; 46 + #interrupt-cells = <2>; 47 + interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>; 48 + }; 49 + };
+21 -223
arch/mips/ath79/irq.c
··· 26 26 #include "common.h" 27 27 #include "machtypes.h" 28 28 29 - static void __init ath79_misc_intc_domain_init( 30 - struct device_node *node, int irq); 31 - 32 - static void ath79_misc_irq_handler(struct irq_desc *desc) 33 - { 34 - struct irq_domain *domain = irq_desc_get_handler_data(desc); 35 - void __iomem *base = domain->host_data; 36 - u32 pending; 37 - 38 - pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) & 39 - __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 40 - 41 - if (!pending) { 42 - spurious_interrupt(); 43 - return; 44 - } 45 - 46 - while (pending) { 47 - int bit = __ffs(pending); 48 - 49 - generic_handle_irq(irq_linear_revmap(domain, bit)); 50 - pending &= ~BIT(bit); 51 - } 52 - } 53 - 54 - static void ar71xx_misc_irq_unmask(struct irq_data *d) 55 - { 56 - void __iomem *base = irq_data_get_irq_chip_data(d); 57 - unsigned int irq = d->hwirq; 58 - u32 t; 59 - 60 - t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 61 - __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 62 - 63 - /* flush write */ 64 - __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 65 - } 66 - 67 - static void ar71xx_misc_irq_mask(struct irq_data *d) 68 - { 69 - void __iomem *base = irq_data_get_irq_chip_data(d); 70 - unsigned int irq = d->hwirq; 71 - u32 t; 72 - 73 - t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 74 - __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 75 - 76 - /* flush write */ 77 - __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 78 - } 79 - 80 - static void ar724x_misc_irq_ack(struct irq_data *d) 81 - { 82 - void __iomem *base = irq_data_get_irq_chip_data(d); 83 - unsigned int irq = d->hwirq; 84 - u32 t; 85 - 86 - t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 87 - __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS); 88 - 89 - /* flush write */ 90 - __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 91 - } 92 - 93 - static struct irq_chip ath79_misc_irq_chip = { 94 - .name = "MISC", 95 - .irq_unmask = ar71xx_misc_irq_unmask, 96 - .irq_mask = ar71xx_misc_irq_mask, 97 - }; 98 - 99 - static void __init ath79_misc_irq_init(void) 100 - { 101 - if (soc_is_ar71xx() || soc_is_ar913x()) 102 - ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; 103 - else if (soc_is_ar724x() || 104 - soc_is_ar933x() || 105 - soc_is_ar934x() || 106 - soc_is_qca955x()) 107 - ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; 108 - else 109 - BUG(); 110 - 111 - ath79_misc_intc_domain_init(NULL, ATH79_CPU_IRQ(6)); 112 - } 113 29 114 30 static void ar934x_ip2_irq_dispatch(struct irq_desc *desc) 115 31 { ··· 128 212 irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); 129 213 } 130 214 131 - /* 132 - * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for 133 - * these devices typically allocate coherent DMA memory, however the 134 - * DMA controller may still have some unsynchronized data in the FIFO. 135 - * Issue a flush in the handlers to ensure that the driver sees 136 - * the update. 137 - * 138 - * This array map the interrupt lines to the DDR write buffer channels. 139 - */ 140 - 141 - static unsigned irq_wb_chan[8] = { 142 - -1, -1, -1, -1, -1, -1, -1, -1, 143 - }; 144 - 145 - asmlinkage void plat_irq_dispatch(void) 146 - { 147 - unsigned long pending; 148 - int irq; 149 - 150 - pending = read_c0_status() & read_c0_cause() & ST0_IM; 151 - 152 - if (!pending) { 153 - spurious_interrupt(); 154 - return; 155 - } 156 - 157 - pending >>= CAUSEB_IP; 158 - while (pending) { 159 - irq = fls(pending) - 1; 160 - if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1) 161 - ath79_ddr_wb_flush(irq_wb_chan[irq]); 162 - do_IRQ(MIPS_CPU_IRQ_BASE + irq); 163 - pending &= ~BIT(irq); 164 - } 165 - } 166 - 167 - static int misc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) 168 - { 169 - irq_set_chip_and_handler(irq, &ath79_misc_irq_chip, handle_level_irq); 170 - irq_set_chip_data(irq, d->host_data); 171 - return 0; 172 - } 173 - 174 - static const struct irq_domain_ops misc_irq_domain_ops = { 175 - .xlate = irq_domain_xlate_onecell, 176 - .map = misc_map, 177 - }; 178 - 179 - static void __init ath79_misc_intc_domain_init( 180 - struct device_node *node, int irq) 181 - { 182 - void __iomem *base = ath79_reset_base; 183 - struct irq_domain *domain; 184 - 185 - domain = irq_domain_add_legacy(node, ATH79_MISC_IRQ_COUNT, 186 - ATH79_MISC_IRQ_BASE, 0, &misc_irq_domain_ops, base); 187 - if (!domain) 188 - panic("Failed to add MISC irqdomain"); 189 - 190 - /* Disable and clear all interrupts */ 191 - __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); 192 - __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); 193 - 194 - irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain); 195 - } 196 - 197 - static int __init ath79_misc_intc_of_init( 198 - struct device_node *node, struct device_node *parent) 199 - { 200 - int irq; 201 - 202 - irq = irq_of_parse_and_map(node, 0); 203 - if (!irq) 204 - panic("Failed to get MISC IRQ"); 205 - 206 - ath79_misc_intc_domain_init(node, irq); 207 - return 0; 208 - } 209 - 210 - static int __init ar7100_misc_intc_of_init( 211 - struct device_node *node, struct device_node *parent) 212 - { 213 - ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; 214 - return ath79_misc_intc_of_init(node, parent); 215 - } 216 - 217 - IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc", 218 - ar7100_misc_intc_of_init); 219 - 220 - static int __init ar7240_misc_intc_of_init( 221 - struct device_node *node, struct device_node *parent) 222 - { 223 - ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; 224 - return ath79_misc_intc_of_init(node, parent); 225 - } 226 - 227 - IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc", 228 - ar7240_misc_intc_of_init); 229 - 230 - static int __init ar79_cpu_intc_of_init( 231 - struct device_node *node, struct device_node *parent) 232 - { 233 - int err, i, count; 234 - 235 - /* Fill the irq_wb_chan table */ 236 - count = of_count_phandle_with_args( 237 - node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); 238 - 239 - for (i = 0; i < count; i++) { 240 - struct of_phandle_args args; 241 - u32 irq = i; 242 - 243 - of_property_read_u32_index( 244 - node, "qca,ddr-wb-channel-interrupts", i, &irq); 245 - if (irq >= ARRAY_SIZE(irq_wb_chan)) 246 - continue; 247 - 248 - err = of_parse_phandle_with_args( 249 - node, "qca,ddr-wb-channels", 250 - "#qca,ddr-wb-channel-cells", 251 - i, &args); 252 - if (err) 253 - return err; 254 - 255 - irq_wb_chan[irq] = args.args[0]; 256 - pr_info("IRQ: Set flush channel of IRQ%d to %d\n", 257 - irq, args.args[0]); 258 - } 259 - 260 - return mips_cpu_irq_of_init(node, parent); 261 - } 262 - IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", 263 - ar79_cpu_intc_of_init); 264 - 265 215 void __init arch_init_irq(void) 266 216 { 217 + unsigned irq_wb_chan2 = -1; 218 + unsigned irq_wb_chan3 = -1; 219 + bool misc_is_ar71xx; 220 + 267 221 if (mips_machtype == ATH79_MACH_GENERIC_OF) { 268 222 irqchip_init(); 269 223 return; ··· 141 355 142 356 if (soc_is_ar71xx() || soc_is_ar724x() || 143 357 soc_is_ar913x() || soc_is_ar933x()) { 144 - irq_wb_chan[2] = 3; 145 - irq_wb_chan[3] = 2; 358 + irq_wb_chan2 = 3; 359 + irq_wb_chan3 = 2; 146 360 } else if (soc_is_ar934x()) { 147 - irq_wb_chan[3] = 2; 361 + irq_wb_chan3 = 2; 148 362 } 149 363 150 - mips_cpu_irq_init(); 151 - ath79_misc_irq_init(); 364 + ath79_cpu_irq_init(irq_wb_chan2, irq_wb_chan3); 365 + 366 + if (soc_is_ar71xx() || soc_is_ar913x()) 367 + misc_is_ar71xx = true; 368 + else if (soc_is_ar724x() || 369 + soc_is_ar933x() || 370 + soc_is_ar934x() || 371 + soc_is_qca955x()) 372 + misc_is_ar71xx = false; 373 + else 374 + BUG(); 375 + ath79_misc_irq_init( 376 + ath79_reset_base + AR71XX_RESET_REG_MISC_INT_STATUS, 377 + ATH79_CPU_IRQ(6), ATH79_MISC_IRQ_BASE, misc_is_ar71xx); 152 378 153 379 if (soc_is_ar934x()) 154 380 ar934x_ip2_irq_init();
+4
arch/mips/include/asm/mach-ath79/ath79.h
··· 144 144 void ath79_device_reset_set(u32 mask); 145 145 void ath79_device_reset_clear(u32 mask); 146 146 147 + void ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3); 148 + void ath79_misc_irq_init(void __iomem *regs, int irq, 149 + int irq_base, bool is_ar71xx); 150 + 147 151 #endif /* __ASM_MACH_ATH79_H */
+9
drivers/irqchip/Kconfig
··· 161 161 help 162 162 Enables SysCfg Controlled IRQs on STi based platforms. 163 163 164 + config TANGO_IRQ 165 + bool 166 + select IRQ_DOMAIN 167 + select GENERIC_IRQ_CHIP 168 + 164 169 config TB10X_IRQC 165 170 bool 166 171 select IRQ_DOMAIN ··· 234 229 def_bool y if MACH_ASM9260 || ARCH_MXS 235 230 select IRQ_DOMAIN 236 231 select STMP_DEVICE 232 + 233 + config MVEBU_ODMI 234 + bool 235 + select GENERIC_MSI_IRQ_DOMAIN
+4
drivers/irqchip/Makefile
··· 1 1 obj-$(CONFIG_IRQCHIP) += irqchip.o 2 2 3 + obj-$(CONFIG_ATH79) += irq-ath79-cpu.o 4 + obj-$(CONFIG_ATH79) += irq-ath79-misc.o 3 5 obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o 4 6 obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o 5 7 obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o ··· 42 40 obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o 43 41 obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o 44 42 obj-$(CONFIG_ST_IRQCHIP) += irq-st.o 43 + obj-$(CONFIG_TANGO_IRQ) += irq-tango.o 45 44 obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o 46 45 obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o 47 46 obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o ··· 63 60 obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o 64 61 obj-$(CONFIG_IMX_GPCV2) += irq-imx-gpcv2.o 65 62 obj-$(CONFIG_PIC32_EVIC) += irq-pic32-evic.o 63 + obj-$(CONFIG_MVEBU_ODMI) += irq-mvebu-odmi.o
+97
drivers/irqchip/irq-ath79-cpu.c
··· 1 + /* 2 + * Atheros AR71xx/AR724x/AR913x specific interrupt handling 3 + * 4 + * Copyright (C) 2015 Alban Bedel <albeu@free.fr> 5 + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 6 + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 7 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 8 + * 9 + * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License version 2 as published 13 + * by the Free Software Foundation. 14 + */ 15 + 16 + #include <linux/interrupt.h> 17 + #include <linux/irqchip.h> 18 + #include <linux/of.h> 19 + 20 + #include <asm/irq_cpu.h> 21 + #include <asm/mach-ath79/ath79.h> 22 + 23 + /* 24 + * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for 25 + * these devices typically allocate coherent DMA memory, however the 26 + * DMA controller may still have some unsynchronized data in the FIFO. 27 + * Issue a flush in the handlers to ensure that the driver sees 28 + * the update. 29 + * 30 + * This array map the interrupt lines to the DDR write buffer channels. 31 + */ 32 + 33 + static unsigned irq_wb_chan[8] = { 34 + -1, -1, -1, -1, -1, -1, -1, -1, 35 + }; 36 + 37 + asmlinkage void plat_irq_dispatch(void) 38 + { 39 + unsigned long pending; 40 + int irq; 41 + 42 + pending = read_c0_status() & read_c0_cause() & ST0_IM; 43 + 44 + if (!pending) { 45 + spurious_interrupt(); 46 + return; 47 + } 48 + 49 + pending >>= CAUSEB_IP; 50 + while (pending) { 51 + irq = fls(pending) - 1; 52 + if (irq < ARRAY_SIZE(irq_wb_chan) && irq_wb_chan[irq] != -1) 53 + ath79_ddr_wb_flush(irq_wb_chan[irq]); 54 + do_IRQ(MIPS_CPU_IRQ_BASE + irq); 55 + pending &= ~BIT(irq); 56 + } 57 + } 58 + 59 + static int __init ar79_cpu_intc_of_init( 60 + struct device_node *node, struct device_node *parent) 61 + { 62 + int err, i, count; 63 + 64 + /* Fill the irq_wb_chan table */ 65 + count = of_count_phandle_with_args( 66 + node, "qca,ddr-wb-channels", "#qca,ddr-wb-channel-cells"); 67 + 68 + for (i = 0; i < count; i++) { 69 + struct of_phandle_args args; 70 + u32 irq = i; 71 + 72 + of_property_read_u32_index( 73 + node, "qca,ddr-wb-channel-interrupts", i, &irq); 74 + if (irq >= ARRAY_SIZE(irq_wb_chan)) 75 + continue; 76 + 77 + err = of_parse_phandle_with_args( 78 + node, "qca,ddr-wb-channels", 79 + "#qca,ddr-wb-channel-cells", 80 + i, &args); 81 + if (err) 82 + return err; 83 + 84 + irq_wb_chan[irq] = args.args[0]; 85 + } 86 + 87 + return mips_cpu_irq_of_init(node, parent); 88 + } 89 + IRQCHIP_DECLARE(ar79_cpu_intc, "qca,ar7100-cpu-intc", 90 + ar79_cpu_intc_of_init); 91 + 92 + void __init ath79_cpu_irq_init(unsigned irq_wb_chan2, unsigned irq_wb_chan3) 93 + { 94 + irq_wb_chan[2] = irq_wb_chan2; 95 + irq_wb_chan[3] = irq_wb_chan3; 96 + mips_cpu_irq_init(); 97 + }
+189
drivers/irqchip/irq-ath79-misc.c
··· 1 + /* 2 + * Atheros AR71xx/AR724x/AR913x MISC interrupt controller 3 + * 4 + * Copyright (C) 2015 Alban Bedel <albeu@free.fr> 5 + * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 6 + * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 7 + * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 8 + * 9 + * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License version 2 as published 13 + * by the Free Software Foundation. 14 + */ 15 + 16 + #include <linux/irqchip.h> 17 + #include <linux/irqchip/chained_irq.h> 18 + #include <linux/of_address.h> 19 + #include <linux/of_irq.h> 20 + 21 + #define AR71XX_RESET_REG_MISC_INT_STATUS 0 22 + #define AR71XX_RESET_REG_MISC_INT_ENABLE 4 23 + 24 + #define ATH79_MISC_IRQ_COUNT 32 25 + 26 + static void ath79_misc_irq_handler(struct irq_desc *desc) 27 + { 28 + struct irq_domain *domain = irq_desc_get_handler_data(desc); 29 + struct irq_chip *chip = irq_desc_get_chip(desc); 30 + void __iomem *base = domain->host_data; 31 + u32 pending; 32 + 33 + chained_irq_enter(chip, desc); 34 + 35 + pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) & 36 + __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 37 + 38 + if (!pending) { 39 + spurious_interrupt(); 40 + chained_irq_exit(chip, desc); 41 + return; 42 + } 43 + 44 + while (pending) { 45 + int bit = __ffs(pending); 46 + 47 + generic_handle_irq(irq_linear_revmap(domain, bit)); 48 + pending &= ~BIT(bit); 49 + } 50 + 51 + chained_irq_exit(chip, desc); 52 + } 53 + 54 + static void ar71xx_misc_irq_unmask(struct irq_data *d) 55 + { 56 + void __iomem *base = irq_data_get_irq_chip_data(d); 57 + unsigned int irq = d->hwirq; 58 + u32 t; 59 + 60 + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 61 + __raw_writel(t | BIT(irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 62 + 63 + /* flush write */ 64 + __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 65 + } 66 + 67 + static void ar71xx_misc_irq_mask(struct irq_data *d) 68 + { 69 + void __iomem *base = irq_data_get_irq_chip_data(d); 70 + unsigned int irq = d->hwirq; 71 + u32 t; 72 + 73 + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 74 + __raw_writel(t & ~BIT(irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 75 + 76 + /* flush write */ 77 + __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 78 + } 79 + 80 + static void ar724x_misc_irq_ack(struct irq_data *d) 81 + { 82 + void __iomem *base = irq_data_get_irq_chip_data(d); 83 + unsigned int irq = d->hwirq; 84 + u32 t; 85 + 86 + t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 87 + __raw_writel(t & ~BIT(irq), base + AR71XX_RESET_REG_MISC_INT_STATUS); 88 + 89 + /* flush write */ 90 + __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 91 + } 92 + 93 + static struct irq_chip ath79_misc_irq_chip = { 94 + .name = "MISC", 95 + .irq_unmask = ar71xx_misc_irq_unmask, 96 + .irq_mask = ar71xx_misc_irq_mask, 97 + }; 98 + 99 + static int misc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) 100 + { 101 + irq_set_chip_and_handler(irq, &ath79_misc_irq_chip, handle_level_irq); 102 + irq_set_chip_data(irq, d->host_data); 103 + return 0; 104 + } 105 + 106 + static const struct irq_domain_ops misc_irq_domain_ops = { 107 + .xlate = irq_domain_xlate_onecell, 108 + .map = misc_map, 109 + }; 110 + 111 + static void __init ath79_misc_intc_domain_init( 112 + struct irq_domain *domain, int irq) 113 + { 114 + void __iomem *base = domain->host_data; 115 + 116 + /* Disable and clear all interrupts */ 117 + __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); 118 + __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); 119 + 120 + irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain); 121 + } 122 + 123 + static int __init ath79_misc_intc_of_init( 124 + struct device_node *node, struct device_node *parent) 125 + { 126 + struct irq_domain *domain; 127 + void __iomem *base; 128 + int irq; 129 + 130 + irq = irq_of_parse_and_map(node, 0); 131 + if (!irq) { 132 + pr_err("Failed to get MISC IRQ\n"); 133 + return -EINVAL; 134 + } 135 + 136 + base = of_iomap(node, 0); 137 + if (!base) { 138 + pr_err("Failed to get MISC IRQ registers\n"); 139 + return -ENOMEM; 140 + } 141 + 142 + domain = irq_domain_add_linear(node, ATH79_MISC_IRQ_COUNT, 143 + &misc_irq_domain_ops, base); 144 + if (!domain) { 145 + pr_err("Failed to add MISC irqdomain\n"); 146 + return -EINVAL; 147 + } 148 + 149 + ath79_misc_intc_domain_init(domain, irq); 150 + return 0; 151 + } 152 + 153 + static int __init ar7100_misc_intc_of_init( 154 + struct device_node *node, struct device_node *parent) 155 + { 156 + ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; 157 + return ath79_misc_intc_of_init(node, parent); 158 + } 159 + 160 + IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc", 161 + ar7100_misc_intc_of_init); 162 + 163 + static int __init ar7240_misc_intc_of_init( 164 + struct device_node *node, struct device_node *parent) 165 + { 166 + ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; 167 + return ath79_misc_intc_of_init(node, parent); 168 + } 169 + 170 + IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc", 171 + ar7240_misc_intc_of_init); 172 + 173 + void __init ath79_misc_irq_init(void __iomem *regs, int irq, 174 + int irq_base, bool is_ar71xx) 175 + { 176 + struct irq_domain *domain; 177 + 178 + if (is_ar71xx) 179 + ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; 180 + else 181 + ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; 182 + 183 + domain = irq_domain_add_legacy(NULL, ATH79_MISC_IRQ_COUNT, 184 + irq_base, 0, &misc_irq_domain_ops, regs); 185 + if (!domain) 186 + panic("Failed to create MISC irqdomain"); 187 + 188 + ath79_misc_intc_domain_init(domain, irq); 189 + }
+1 -13
drivers/irqchip/irq-gic-v2m.c
··· 92 92 .chip = &gicv2m_msi_irq_chip, 93 93 }; 94 94 95 - static int gicv2m_set_affinity(struct irq_data *irq_data, 96 - const struct cpumask *mask, bool force) 97 - { 98 - int ret; 99 - 100 - ret = irq_chip_set_affinity_parent(irq_data, mask, force); 101 - if (ret == IRQ_SET_MASK_OK) 102 - ret = IRQ_SET_MASK_OK_DONE; 103 - 104 - return ret; 105 - } 106 - 107 95 static void gicv2m_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 108 96 { 109 97 struct v2m_data *v2m = irq_data_get_irq_chip_data(data); ··· 110 122 .irq_mask = irq_chip_mask_parent, 111 123 .irq_unmask = irq_chip_unmask_parent, 112 124 .irq_eoi = irq_chip_eoi_parent, 113 - .irq_set_affinity = gicv2m_set_affinity, 125 + .irq_set_affinity = irq_chip_set_affinity_parent, 114 126 .irq_compose_msi_msg = gicv2m_compose_msi_msg, 115 127 }; 116 128
+1 -1
drivers/irqchip/irq-gic.c
··· 319 319 writel_relaxed(val | bit, reg); 320 320 raw_spin_unlock_irqrestore(&irq_controller_lock, flags); 321 321 322 - return IRQ_SET_MASK_OK; 322 + return IRQ_SET_MASK_OK_DONE; 323 323 } 324 324 #endif 325 325
+236
drivers/irqchip/irq-mvebu-odmi.c
··· 1 + /* 2 + * Copyright (C) 2016 Marvell 3 + * 4 + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 5 + * 6 + * This file is licensed under the terms of the GNU General Public 7 + * License version 2. This program is licensed "as is" without any 8 + * warranty of any kind, whether express or implied. 9 + */ 10 + 11 + #define pr_fmt(fmt) "GIC-ODMI: " fmt 12 + 13 + #include <linux/irq.h> 14 + #include <linux/irqchip.h> 15 + #include <linux/irqdomain.h> 16 + #include <linux/kernel.h> 17 + #include <linux/msi.h> 18 + #include <linux/of_address.h> 19 + #include <linux/slab.h> 20 + #include <dt-bindings/interrupt-controller/arm-gic.h> 21 + 22 + #define GICP_ODMIN_SET 0x40 23 + #define GICP_ODMI_INT_NUM_SHIFT 12 24 + #define GICP_ODMIN_GM_EP_R0 0x110 25 + #define GICP_ODMIN_GM_EP_R1 0x114 26 + #define GICP_ODMIN_GM_EA_R0 0x108 27 + #define GICP_ODMIN_GM_EA_R1 0x118 28 + 29 + /* 30 + * We don't support the group events, so we simply have 8 interrupts 31 + * per frame. 32 + */ 33 + #define NODMIS_SHIFT 3 34 + #define NODMIS_PER_FRAME (1 << NODMIS_SHIFT) 35 + #define NODMIS_MASK (NODMIS_PER_FRAME - 1) 36 + 37 + struct odmi_data { 38 + struct resource res; 39 + void __iomem *base; 40 + unsigned int spi_base; 41 + }; 42 + 43 + static struct odmi_data *odmis; 44 + static unsigned long *odmis_bm; 45 + static unsigned int odmis_count; 46 + 47 + /* Protects odmis_bm */ 48 + static DEFINE_SPINLOCK(odmis_bm_lock); 49 + 50 + static void odmi_compose_msi_msg(struct irq_data *d, struct msi_msg *msg) 51 + { 52 + struct odmi_data *odmi; 53 + phys_addr_t addr; 54 + unsigned int odmin; 55 + 56 + if (WARN_ON(d->hwirq >= odmis_count * NODMIS_PER_FRAME)) 57 + return; 58 + 59 + odmi = &odmis[d->hwirq >> NODMIS_SHIFT]; 60 + odmin = d->hwirq & NODMIS_MASK; 61 + 62 + addr = odmi->res.start + GICP_ODMIN_SET; 63 + 64 + msg->address_hi = upper_32_bits(addr); 65 + msg->address_lo = lower_32_bits(addr); 66 + msg->data = odmin << GICP_ODMI_INT_NUM_SHIFT; 67 + } 68 + 69 + static struct irq_chip odmi_irq_chip = { 70 + .name = "ODMI", 71 + .irq_mask = irq_chip_mask_parent, 72 + .irq_unmask = irq_chip_unmask_parent, 73 + .irq_eoi = irq_chip_eoi_parent, 74 + .irq_set_affinity = irq_chip_set_affinity_parent, 75 + .irq_compose_msi_msg = odmi_compose_msi_msg, 76 + }; 77 + 78 + static int odmi_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, 79 + unsigned int nr_irqs, void *args) 80 + { 81 + struct odmi_data *odmi = NULL; 82 + struct irq_fwspec fwspec; 83 + struct irq_data *d; 84 + unsigned int hwirq, odmin; 85 + int ret; 86 + 87 + spin_lock(&odmis_bm_lock); 88 + hwirq = find_first_zero_bit(odmis_bm, NODMIS_PER_FRAME * odmis_count); 89 + if (hwirq >= NODMIS_PER_FRAME * odmis_count) { 90 + spin_unlock(&odmis_bm_lock); 91 + return -ENOSPC; 92 + } 93 + 94 + __set_bit(hwirq, odmis_bm); 95 + spin_unlock(&odmis_bm_lock); 96 + 97 + odmi = &odmis[hwirq >> NODMIS_SHIFT]; 98 + odmin = hwirq & NODMIS_MASK; 99 + 100 + fwspec.fwnode = domain->parent->fwnode; 101 + fwspec.param_count = 3; 102 + fwspec.param[0] = GIC_SPI; 103 + fwspec.param[1] = odmi->spi_base - 32 + odmin; 104 + fwspec.param[2] = IRQ_TYPE_EDGE_RISING; 105 + 106 + ret = irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec); 107 + if (ret) { 108 + pr_err("Cannot allocate parent IRQ\n"); 109 + spin_lock(&odmis_bm_lock); 110 + __clear_bit(odmin, odmis_bm); 111 + spin_unlock(&odmis_bm_lock); 112 + return ret; 113 + } 114 + 115 + /* Configure the interrupt line to be edge */ 116 + d = irq_domain_get_irq_data(domain->parent, virq); 117 + d->chip->irq_set_type(d, IRQ_TYPE_EDGE_RISING); 118 + 119 + irq_domain_set_hwirq_and_chip(domain, virq, hwirq, 120 + &odmi_irq_chip, NULL); 121 + 122 + return 0; 123 + } 124 + 125 + static void odmi_irq_domain_free(struct irq_domain *domain, 126 + unsigned int virq, unsigned int nr_irqs) 127 + { 128 + struct irq_data *d = irq_domain_get_irq_data(domain, virq); 129 + 130 + if (d->hwirq >= odmis_count * NODMIS_PER_FRAME) { 131 + pr_err("Failed to teardown msi. Invalid hwirq %lu\n", d->hwirq); 132 + return; 133 + } 134 + 135 + irq_domain_free_irqs_parent(domain, virq, nr_irqs); 136 + 137 + /* Actually free the MSI */ 138 + spin_lock(&odmis_bm_lock); 139 + __clear_bit(d->hwirq, odmis_bm); 140 + spin_unlock(&odmis_bm_lock); 141 + } 142 + 143 + static const struct irq_domain_ops odmi_domain_ops = { 144 + .alloc = odmi_irq_domain_alloc, 145 + .free = odmi_irq_domain_free, 146 + }; 147 + 148 + static struct irq_chip odmi_msi_irq_chip = { 149 + .name = "ODMI", 150 + }; 151 + 152 + static struct msi_domain_ops odmi_msi_ops = { 153 + }; 154 + 155 + static struct msi_domain_info odmi_msi_domain_info = { 156 + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS), 157 + .ops = &odmi_msi_ops, 158 + .chip = &odmi_msi_irq_chip, 159 + }; 160 + 161 + static int __init mvebu_odmi_init(struct device_node *node, 162 + struct device_node *parent) 163 + { 164 + struct irq_domain *inner_domain, *plat_domain; 165 + int ret, i; 166 + 167 + if (of_property_read_u32(node, "marvell,odmi-frames", &odmis_count)) 168 + return -EINVAL; 169 + 170 + odmis = kcalloc(odmis_count, sizeof(struct odmi_data), GFP_KERNEL); 171 + if (!odmis) 172 + return -ENOMEM; 173 + 174 + odmis_bm = kcalloc(BITS_TO_LONGS(odmis_count * NODMIS_PER_FRAME), 175 + sizeof(long), GFP_KERNEL); 176 + if (!odmis_bm) { 177 + ret = -ENOMEM; 178 + goto err_alloc; 179 + } 180 + 181 + for (i = 0; i < odmis_count; i++) { 182 + struct odmi_data *odmi = &odmis[i]; 183 + 184 + ret = of_address_to_resource(node, i, &odmi->res); 185 + if (ret) 186 + goto err_unmap; 187 + 188 + odmi->base = of_io_request_and_map(node, i, "odmi"); 189 + if (IS_ERR(odmi->base)) { 190 + ret = PTR_ERR(odmi->base); 191 + goto err_unmap; 192 + } 193 + 194 + if (of_property_read_u32_index(node, "marvell,spi-base", 195 + i, &odmi->spi_base)) { 196 + ret = -EINVAL; 197 + goto err_unmap; 198 + } 199 + } 200 + 201 + inner_domain = irq_domain_create_linear(of_node_to_fwnode(node), 202 + odmis_count * NODMIS_PER_FRAME, 203 + &odmi_domain_ops, NULL); 204 + if (!inner_domain) { 205 + ret = -ENOMEM; 206 + goto err_unmap; 207 + } 208 + 209 + inner_domain->parent = irq_find_host(parent); 210 + 211 + plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(node), 212 + &odmi_msi_domain_info, 213 + inner_domain); 214 + if (!plat_domain) { 215 + ret = -ENOMEM; 216 + goto err_remove_inner; 217 + } 218 + 219 + return 0; 220 + 221 + err_remove_inner: 222 + irq_domain_remove(inner_domain); 223 + err_unmap: 224 + for (i = 0; i < odmis_count; i++) { 225 + struct odmi_data *odmi = &odmis[i]; 226 + 227 + if (odmi->base && !IS_ERR(odmi->base)) 228 + iounmap(odmis[i].base); 229 + } 230 + kfree(odmis_bm); 231 + err_alloc: 232 + kfree(odmis); 233 + return ret; 234 + } 235 + 236 + IRQCHIP_DECLARE(mvebu_odmi, "marvell,odmi-controller", mvebu_odmi_init);
+232
drivers/irqchip/irq-tango.c
··· 1 + /* 2 + * Copyright (C) 2014 Mans Rullgard <mans@mansr.com> 3 + * 4 + * This program is free software; you can redistribute it and/or modify it 5 + * under the terms of the GNU General Public License as published by the 6 + * Free Software Foundation; either version 2 of the License, or (at your 7 + * option) any later version. 8 + */ 9 + 10 + #include <linux/init.h> 11 + #include <linux/irq.h> 12 + #include <linux/irqchip.h> 13 + #include <linux/irqchip/chained_irq.h> 14 + #include <linux/ioport.h> 15 + #include <linux/io.h> 16 + #include <linux/of_address.h> 17 + #include <linux/of_irq.h> 18 + #include <linux/slab.h> 19 + 20 + #define IRQ0_CTL_BASE 0x0000 21 + #define IRQ1_CTL_BASE 0x0100 22 + #define EDGE_CTL_BASE 0x0200 23 + #define IRQ2_CTL_BASE 0x0300 24 + 25 + #define IRQ_CTL_HI 0x18 26 + #define EDGE_CTL_HI 0x20 27 + 28 + #define IRQ_STATUS 0x00 29 + #define IRQ_RAWSTAT 0x04 30 + #define IRQ_EN_SET 0x08 31 + #define IRQ_EN_CLR 0x0c 32 + #define IRQ_SOFT_SET 0x10 33 + #define IRQ_SOFT_CLR 0x14 34 + 35 + #define EDGE_STATUS 0x00 36 + #define EDGE_RAWSTAT 0x04 37 + #define EDGE_CFG_RISE 0x08 38 + #define EDGE_CFG_FALL 0x0c 39 + #define EDGE_CFG_RISE_SET 0x10 40 + #define EDGE_CFG_RISE_CLR 0x14 41 + #define EDGE_CFG_FALL_SET 0x18 42 + #define EDGE_CFG_FALL_CLR 0x1c 43 + 44 + struct tangox_irq_chip { 45 + void __iomem *base; 46 + unsigned long ctl; 47 + }; 48 + 49 + static inline u32 intc_readl(struct tangox_irq_chip *chip, int reg) 50 + { 51 + return readl_relaxed(chip->base + reg); 52 + } 53 + 54 + static inline void intc_writel(struct tangox_irq_chip *chip, int reg, u32 val) 55 + { 56 + writel_relaxed(val, chip->base + reg); 57 + } 58 + 59 + static void tangox_dispatch_irqs(struct irq_domain *dom, unsigned int status, 60 + int base) 61 + { 62 + unsigned int hwirq; 63 + unsigned int virq; 64 + 65 + while (status) { 66 + hwirq = __ffs(status); 67 + virq = irq_find_mapping(dom, base + hwirq); 68 + if (virq) 69 + generic_handle_irq(virq); 70 + status &= ~BIT(hwirq); 71 + } 72 + } 73 + 74 + static void tangox_irq_handler(struct irq_desc *desc) 75 + { 76 + struct irq_domain *dom = irq_desc_get_handler_data(desc); 77 + struct irq_chip *host_chip = irq_desc_get_chip(desc); 78 + struct tangox_irq_chip *chip = dom->host_data; 79 + unsigned int status_lo, status_hi; 80 + 81 + chained_irq_enter(host_chip, desc); 82 + 83 + status_lo = intc_readl(chip, chip->ctl + IRQ_STATUS); 84 + status_hi = intc_readl(chip, chip->ctl + IRQ_CTL_HI + IRQ_STATUS); 85 + 86 + tangox_dispatch_irqs(dom, status_lo, 0); 87 + tangox_dispatch_irqs(dom, status_hi, 32); 88 + 89 + chained_irq_exit(host_chip, desc); 90 + } 91 + 92 + static int tangox_irq_set_type(struct irq_data *d, unsigned int flow_type) 93 + { 94 + struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); 95 + struct tangox_irq_chip *chip = gc->domain->host_data; 96 + struct irq_chip_regs *regs = &gc->chip_types[0].regs; 97 + 98 + switch (flow_type & IRQ_TYPE_SENSE_MASK) { 99 + case IRQ_TYPE_EDGE_RISING: 100 + intc_writel(chip, regs->type + EDGE_CFG_RISE_SET, d->mask); 101 + intc_writel(chip, regs->type + EDGE_CFG_FALL_CLR, d->mask); 102 + break; 103 + 104 + case IRQ_TYPE_EDGE_FALLING: 105 + intc_writel(chip, regs->type + EDGE_CFG_RISE_CLR, d->mask); 106 + intc_writel(chip, regs->type + EDGE_CFG_FALL_SET, d->mask); 107 + break; 108 + 109 + case IRQ_TYPE_LEVEL_HIGH: 110 + intc_writel(chip, regs->type + EDGE_CFG_RISE_CLR, d->mask); 111 + intc_writel(chip, regs->type + EDGE_CFG_FALL_CLR, d->mask); 112 + break; 113 + 114 + case IRQ_TYPE_LEVEL_LOW: 115 + intc_writel(chip, regs->type + EDGE_CFG_RISE_SET, d->mask); 116 + intc_writel(chip, regs->type + EDGE_CFG_FALL_SET, d->mask); 117 + break; 118 + 119 + default: 120 + pr_err("Invalid trigger mode %x for IRQ %d\n", 121 + flow_type, d->irq); 122 + return -EINVAL; 123 + } 124 + 125 + return irq_setup_alt_chip(d, flow_type); 126 + } 127 + 128 + static void __init tangox_irq_init_chip(struct irq_chip_generic *gc, 129 + unsigned long ctl_offs, 130 + unsigned long edge_offs) 131 + { 132 + struct tangox_irq_chip *chip = gc->domain->host_data; 133 + struct irq_chip_type *ct = gc->chip_types; 134 + unsigned long ctl_base = chip->ctl + ctl_offs; 135 + unsigned long edge_base = EDGE_CTL_BASE + edge_offs; 136 + int i; 137 + 138 + gc->reg_base = chip->base; 139 + gc->unused = 0; 140 + 141 + for (i = 0; i < 2; i++) { 142 + ct[i].chip.irq_ack = irq_gc_ack_set_bit; 143 + ct[i].chip.irq_mask = irq_gc_mask_disable_reg; 144 + ct[i].chip.irq_mask_ack = irq_gc_mask_disable_reg_and_ack; 145 + ct[i].chip.irq_unmask = irq_gc_unmask_enable_reg; 146 + ct[i].chip.irq_set_type = tangox_irq_set_type; 147 + ct[i].chip.name = gc->domain->name; 148 + 149 + ct[i].regs.enable = ctl_base + IRQ_EN_SET; 150 + ct[i].regs.disable = ctl_base + IRQ_EN_CLR; 151 + ct[i].regs.ack = edge_base + EDGE_RAWSTAT; 152 + ct[i].regs.type = edge_base; 153 + } 154 + 155 + ct[0].type = IRQ_TYPE_LEVEL_MASK; 156 + ct[0].handler = handle_level_irq; 157 + 158 + ct[1].type = IRQ_TYPE_EDGE_BOTH; 159 + ct[1].handler = handle_edge_irq; 160 + 161 + intc_writel(chip, ct->regs.disable, 0xffffffff); 162 + intc_writel(chip, ct->regs.ack, 0xffffffff); 163 + } 164 + 165 + static void __init tangox_irq_domain_init(struct irq_domain *dom) 166 + { 167 + struct irq_chip_generic *gc; 168 + int i; 169 + 170 + for (i = 0; i < 2; i++) { 171 + gc = irq_get_domain_generic_chip(dom, i * 32); 172 + tangox_irq_init_chip(gc, i * IRQ_CTL_HI, i * EDGE_CTL_HI); 173 + } 174 + } 175 + 176 + static int __init tangox_irq_init(void __iomem *base, struct resource *baseres, 177 + struct device_node *node) 178 + { 179 + struct tangox_irq_chip *chip; 180 + struct irq_domain *dom; 181 + struct resource res; 182 + int irq; 183 + int err; 184 + 185 + irq = irq_of_parse_and_map(node, 0); 186 + if (!irq) 187 + panic("%s: failed to get IRQ", node->name); 188 + 189 + err = of_address_to_resource(node, 0, &res); 190 + if (err) 191 + panic("%s: failed to get address", node->name); 192 + 193 + chip = kzalloc(sizeof(*chip), GFP_KERNEL); 194 + chip->ctl = res.start - baseres->start; 195 + chip->base = base; 196 + 197 + dom = irq_domain_add_linear(node, 64, &irq_generic_chip_ops, chip); 198 + if (!dom) 199 + panic("%s: failed to create irqdomain", node->name); 200 + 201 + err = irq_alloc_domain_generic_chips(dom, 32, 2, node->name, 202 + handle_level_irq, 0, 0, 0); 203 + if (err) 204 + panic("%s: failed to allocate irqchip", node->name); 205 + 206 + tangox_irq_domain_init(dom); 207 + 208 + irq_set_chained_handler(irq, tangox_irq_handler); 209 + irq_set_handler_data(irq, dom); 210 + 211 + return 0; 212 + } 213 + 214 + static int __init tangox_of_irq_init(struct device_node *node, 215 + struct device_node *parent) 216 + { 217 + struct device_node *c; 218 + struct resource res; 219 + void __iomem *base; 220 + 221 + base = of_iomap(node, 0); 222 + if (!base) 223 + panic("%s: of_iomap failed", node->name); 224 + 225 + of_address_to_resource(node, 0, &res); 226 + 227 + for_each_child_of_node(node, c) 228 + tangox_irq_init(base, &res, c); 229 + 230 + return 0; 231 + } 232 + IRQCHIP_DECLARE(tangox_intc, "sigma,smp8642-intc", tangox_of_irq_init);