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

Merge branch 'irqchip/mips' into irqchip/core

+313 -223
+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 */
+2
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
+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 + }