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

Configure Feed

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

at v3.8-rc7 301 lines 7.5 kB view raw
1/* 2 * Atheros AR71xx/AR724x/AR913x specific interrupt handling 3 * 4 * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com> 5 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> 6 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> 7 * 8 * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published 12 * by the Free Software Foundation. 13 */ 14 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/interrupt.h> 18#include <linux/irq.h> 19 20#include <asm/irq_cpu.h> 21#include <asm/mipsregs.h> 22 23#include <asm/mach-ath79/ath79.h> 24#include <asm/mach-ath79/ar71xx_regs.h> 25#include "common.h" 26 27static void (*ath79_ip2_handler)(void); 28static void (*ath79_ip3_handler)(void); 29 30static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) 31{ 32 void __iomem *base = ath79_reset_base; 33 u32 pending; 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 & MISC_INT_UART) 39 generic_handle_irq(ATH79_MISC_IRQ_UART); 40 41 else if (pending & MISC_INT_DMA) 42 generic_handle_irq(ATH79_MISC_IRQ_DMA); 43 44 else if (pending & MISC_INT_PERFC) 45 generic_handle_irq(ATH79_MISC_IRQ_PERFC); 46 47 else if (pending & MISC_INT_TIMER) 48 generic_handle_irq(ATH79_MISC_IRQ_TIMER); 49 50 else if (pending & MISC_INT_TIMER2) 51 generic_handle_irq(ATH79_MISC_IRQ_TIMER2); 52 53 else if (pending & MISC_INT_TIMER3) 54 generic_handle_irq(ATH79_MISC_IRQ_TIMER3); 55 56 else if (pending & MISC_INT_TIMER4) 57 generic_handle_irq(ATH79_MISC_IRQ_TIMER4); 58 59 else if (pending & MISC_INT_OHCI) 60 generic_handle_irq(ATH79_MISC_IRQ_OHCI); 61 62 else if (pending & MISC_INT_ERROR) 63 generic_handle_irq(ATH79_MISC_IRQ_ERROR); 64 65 else if (pending & MISC_INT_GPIO) 66 generic_handle_irq(ATH79_MISC_IRQ_GPIO); 67 68 else if (pending & MISC_INT_WDOG) 69 generic_handle_irq(ATH79_MISC_IRQ_WDOG); 70 71 else if (pending & MISC_INT_ETHSW) 72 generic_handle_irq(ATH79_MISC_IRQ_ETHSW); 73 74 else 75 spurious_interrupt(); 76} 77 78static void ar71xx_misc_irq_unmask(struct irq_data *d) 79{ 80 unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; 81 void __iomem *base = ath79_reset_base; 82 u32 t; 83 84 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 85 __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 86 87 /* flush write */ 88 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 89} 90 91static void ar71xx_misc_irq_mask(struct irq_data *d) 92{ 93 unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; 94 void __iomem *base = ath79_reset_base; 95 u32 t; 96 97 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 98 __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 99 100 /* flush write */ 101 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 102} 103 104static void ar724x_misc_irq_ack(struct irq_data *d) 105{ 106 unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; 107 void __iomem *base = ath79_reset_base; 108 u32 t; 109 110 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 111 __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS); 112 113 /* flush write */ 114 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 115} 116 117static struct irq_chip ath79_misc_irq_chip = { 118 .name = "MISC", 119 .irq_unmask = ar71xx_misc_irq_unmask, 120 .irq_mask = ar71xx_misc_irq_mask, 121}; 122 123static void __init ath79_misc_irq_init(void) 124{ 125 void __iomem *base = ath79_reset_base; 126 int i; 127 128 __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); 129 __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); 130 131 if (soc_is_ar71xx() || soc_is_ar913x()) 132 ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; 133 else if (soc_is_ar724x() || soc_is_ar933x() || soc_is_ar934x()) 134 ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; 135 else 136 BUG(); 137 138 for (i = ATH79_MISC_IRQ_BASE; 139 i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) { 140 irq_set_chip_and_handler(i, &ath79_misc_irq_chip, 141 handle_level_irq); 142 } 143 144 irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler); 145} 146 147static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) 148{ 149 u32 status; 150 151 disable_irq_nosync(irq); 152 153 status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS); 154 155 if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) { 156 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE); 157 generic_handle_irq(ATH79_IP2_IRQ(0)); 158 } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) { 159 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC); 160 generic_handle_irq(ATH79_IP2_IRQ(1)); 161 } else { 162 spurious_interrupt(); 163 } 164 165 enable_irq(irq); 166} 167 168static void ar934x_ip2_irq_init(void) 169{ 170 int i; 171 172 for (i = ATH79_IP2_IRQ_BASE; 173 i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) 174 irq_set_chip_and_handler(i, &dummy_irq_chip, 175 handle_level_irq); 176 177 irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar934x_ip2_irq_dispatch); 178} 179 180asmlinkage void plat_irq_dispatch(void) 181{ 182 unsigned long pending; 183 184 pending = read_c0_status() & read_c0_cause() & ST0_IM; 185 186 if (pending & STATUSF_IP7) 187 do_IRQ(ATH79_CPU_IRQ_TIMER); 188 189 else if (pending & STATUSF_IP2) 190 ath79_ip2_handler(); 191 192 else if (pending & STATUSF_IP4) 193 do_IRQ(ATH79_CPU_IRQ_GE0); 194 195 else if (pending & STATUSF_IP5) 196 do_IRQ(ATH79_CPU_IRQ_GE1); 197 198 else if (pending & STATUSF_IP3) 199 ath79_ip3_handler(); 200 201 else if (pending & STATUSF_IP6) 202 do_IRQ(ATH79_CPU_IRQ_MISC); 203 204 else 205 spurious_interrupt(); 206} 207 208/* 209 * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for 210 * these devices typically allocate coherent DMA memory, however the 211 * DMA controller may still have some unsynchronized data in the FIFO. 212 * Issue a flush in the handlers to ensure that the driver sees 213 * the update. 214 */ 215static void ar71xx_ip2_handler(void) 216{ 217 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); 218 do_IRQ(ATH79_CPU_IRQ_IP2); 219} 220 221static void ar724x_ip2_handler(void) 222{ 223 ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); 224 do_IRQ(ATH79_CPU_IRQ_IP2); 225} 226 227static void ar913x_ip2_handler(void) 228{ 229 ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); 230 do_IRQ(ATH79_CPU_IRQ_IP2); 231} 232 233static void ar933x_ip2_handler(void) 234{ 235 ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC); 236 do_IRQ(ATH79_CPU_IRQ_IP2); 237} 238 239static void ar934x_ip2_handler(void) 240{ 241 do_IRQ(ATH79_CPU_IRQ_IP2); 242} 243 244static void ar71xx_ip3_handler(void) 245{ 246 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); 247 do_IRQ(ATH79_CPU_IRQ_USB); 248} 249 250static void ar724x_ip3_handler(void) 251{ 252 ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); 253 do_IRQ(ATH79_CPU_IRQ_USB); 254} 255 256static void ar913x_ip3_handler(void) 257{ 258 ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); 259 do_IRQ(ATH79_CPU_IRQ_USB); 260} 261 262static void ar933x_ip3_handler(void) 263{ 264 ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); 265 do_IRQ(ATH79_CPU_IRQ_USB); 266} 267 268static void ar934x_ip3_handler(void) 269{ 270 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB); 271 do_IRQ(ATH79_CPU_IRQ_USB); 272} 273 274void __init arch_init_irq(void) 275{ 276 if (soc_is_ar71xx()) { 277 ath79_ip2_handler = ar71xx_ip2_handler; 278 ath79_ip3_handler = ar71xx_ip3_handler; 279 } else if (soc_is_ar724x()) { 280 ath79_ip2_handler = ar724x_ip2_handler; 281 ath79_ip3_handler = ar724x_ip3_handler; 282 } else if (soc_is_ar913x()) { 283 ath79_ip2_handler = ar913x_ip2_handler; 284 ath79_ip3_handler = ar913x_ip3_handler; 285 } else if (soc_is_ar933x()) { 286 ath79_ip2_handler = ar933x_ip2_handler; 287 ath79_ip3_handler = ar933x_ip3_handler; 288 } else if (soc_is_ar934x()) { 289 ath79_ip2_handler = ar934x_ip2_handler; 290 ath79_ip3_handler = ar934x_ip3_handler; 291 } else { 292 BUG(); 293 } 294 295 cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; 296 mips_cpu_irq_init(); 297 ath79_misc_irq_init(); 298 299 if (soc_is_ar934x()) 300 ar934x_ip2_irq_init(); 301}