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) { 39 spurious_interrupt(); 40 return; 41 } 42 43 while (pending) { 44 int bit = __ffs(pending); 45 46 generic_handle_irq(ATH79_MISC_IRQ(bit)); 47 pending &= ~BIT(bit); 48 } 49} 50 51static void ar71xx_misc_irq_unmask(struct irq_data *d) 52{ 53 unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; 54 void __iomem *base = ath79_reset_base; 55 u32 t; 56 57 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 58 __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 59 60 /* flush write */ 61 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 62} 63 64static void ar71xx_misc_irq_mask(struct irq_data *d) 65{ 66 unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; 67 void __iomem *base = ath79_reset_base; 68 u32 t; 69 70 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 71 __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE); 72 73 /* flush write */ 74 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE); 75} 76 77static void ar724x_misc_irq_ack(struct irq_data *d) 78{ 79 unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE; 80 void __iomem *base = ath79_reset_base; 81 u32 t; 82 83 t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 84 __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS); 85 86 /* flush write */ 87 __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS); 88} 89 90static struct irq_chip ath79_misc_irq_chip = { 91 .name = "MISC", 92 .irq_unmask = ar71xx_misc_irq_unmask, 93 .irq_mask = ar71xx_misc_irq_mask, 94}; 95 96static void __init ath79_misc_irq_init(void) 97{ 98 void __iomem *base = ath79_reset_base; 99 int i; 100 101 __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); 102 __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); 103 104 if (soc_is_ar71xx() || soc_is_ar913x()) 105 ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; 106 else if (soc_is_ar724x() || 107 soc_is_ar933x() || 108 soc_is_ar934x() || 109 soc_is_qca955x()) 110 ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; 111 else 112 BUG(); 113 114 for (i = ATH79_MISC_IRQ_BASE; 115 i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) { 116 irq_set_chip_and_handler(i, &ath79_misc_irq_chip, 117 handle_level_irq); 118 } 119 120 irq_set_chained_handler(ATH79_CPU_IRQ(6), ath79_misc_irq_handler); 121} 122 123static void ar934x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) 124{ 125 u32 status; 126 127 disable_irq_nosync(irq); 128 129 status = ath79_reset_rr(AR934X_RESET_REG_PCIE_WMAC_INT_STATUS); 130 131 if (status & AR934X_PCIE_WMAC_INT_PCIE_ALL) { 132 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_PCIE); 133 generic_handle_irq(ATH79_IP2_IRQ(0)); 134 } else if (status & AR934X_PCIE_WMAC_INT_WMAC_ALL) { 135 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_WMAC); 136 generic_handle_irq(ATH79_IP2_IRQ(1)); 137 } else { 138 spurious_interrupt(); 139 } 140 141 enable_irq(irq); 142} 143 144static void ar934x_ip2_irq_init(void) 145{ 146 int i; 147 148 for (i = ATH79_IP2_IRQ_BASE; 149 i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) 150 irq_set_chip_and_handler(i, &dummy_irq_chip, 151 handle_level_irq); 152 153 irq_set_chained_handler(ATH79_CPU_IRQ(2), ar934x_ip2_irq_dispatch); 154} 155 156static void qca955x_ip2_irq_dispatch(unsigned int irq, struct irq_desc *desc) 157{ 158 u32 status; 159 160 disable_irq_nosync(irq); 161 162 status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS); 163 status &= QCA955X_EXT_INT_PCIE_RC1_ALL | QCA955X_EXT_INT_WMAC_ALL; 164 165 if (status == 0) { 166 spurious_interrupt(); 167 goto enable; 168 } 169 170 if (status & QCA955X_EXT_INT_PCIE_RC1_ALL) { 171 /* TODO: flush DDR? */ 172 generic_handle_irq(ATH79_IP2_IRQ(0)); 173 } 174 175 if (status & QCA955X_EXT_INT_WMAC_ALL) { 176 /* TODO: flush DDR? */ 177 generic_handle_irq(ATH79_IP2_IRQ(1)); 178 } 179 180enable: 181 enable_irq(irq); 182} 183 184static void qca955x_ip3_irq_dispatch(unsigned int irq, struct irq_desc *desc) 185{ 186 u32 status; 187 188 disable_irq_nosync(irq); 189 190 status = ath79_reset_rr(QCA955X_RESET_REG_EXT_INT_STATUS); 191 status &= QCA955X_EXT_INT_PCIE_RC2_ALL | 192 QCA955X_EXT_INT_USB1 | 193 QCA955X_EXT_INT_USB2; 194 195 if (status == 0) { 196 spurious_interrupt(); 197 goto enable; 198 } 199 200 if (status & QCA955X_EXT_INT_USB1) { 201 /* TODO: flush DDR? */ 202 generic_handle_irq(ATH79_IP3_IRQ(0)); 203 } 204 205 if (status & QCA955X_EXT_INT_USB2) { 206 /* TODO: flush DDR? */ 207 generic_handle_irq(ATH79_IP3_IRQ(1)); 208 } 209 210 if (status & QCA955X_EXT_INT_PCIE_RC2_ALL) { 211 /* TODO: flush DDR? */ 212 generic_handle_irq(ATH79_IP3_IRQ(2)); 213 } 214 215enable: 216 enable_irq(irq); 217} 218 219static void qca955x_irq_init(void) 220{ 221 int i; 222 223 for (i = ATH79_IP2_IRQ_BASE; 224 i < ATH79_IP2_IRQ_BASE + ATH79_IP2_IRQ_COUNT; i++) 225 irq_set_chip_and_handler(i, &dummy_irq_chip, 226 handle_level_irq); 227 228 irq_set_chained_handler(ATH79_CPU_IRQ(2), qca955x_ip2_irq_dispatch); 229 230 for (i = ATH79_IP3_IRQ_BASE; 231 i < ATH79_IP3_IRQ_BASE + ATH79_IP3_IRQ_COUNT; i++) 232 irq_set_chip_and_handler(i, &dummy_irq_chip, 233 handle_level_irq); 234 235 irq_set_chained_handler(ATH79_CPU_IRQ(3), qca955x_ip3_irq_dispatch); 236} 237 238asmlinkage void plat_irq_dispatch(void) 239{ 240 unsigned long pending; 241 242 pending = read_c0_status() & read_c0_cause() & ST0_IM; 243 244 if (pending & STATUSF_IP7) 245 do_IRQ(ATH79_CPU_IRQ(7)); 246 247 else if (pending & STATUSF_IP2) 248 ath79_ip2_handler(); 249 250 else if (pending & STATUSF_IP4) 251 do_IRQ(ATH79_CPU_IRQ(4)); 252 253 else if (pending & STATUSF_IP5) 254 do_IRQ(ATH79_CPU_IRQ(5)); 255 256 else if (pending & STATUSF_IP3) 257 ath79_ip3_handler(); 258 259 else if (pending & STATUSF_IP6) 260 do_IRQ(ATH79_CPU_IRQ(6)); 261 262 else 263 spurious_interrupt(); 264} 265 266/* 267 * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for 268 * these devices typically allocate coherent DMA memory, however the 269 * DMA controller may still have some unsynchronized data in the FIFO. 270 * Issue a flush in the handlers to ensure that the driver sees 271 * the update. 272 */ 273 274static void ath79_default_ip2_handler(void) 275{ 276 do_IRQ(ATH79_CPU_IRQ(2)); 277} 278 279static void ath79_default_ip3_handler(void) 280{ 281 do_IRQ(ATH79_CPU_IRQ(3)); 282} 283 284static void ar71xx_ip2_handler(void) 285{ 286 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); 287 do_IRQ(ATH79_CPU_IRQ(2)); 288} 289 290static void ar724x_ip2_handler(void) 291{ 292 ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); 293 do_IRQ(ATH79_CPU_IRQ(2)); 294} 295 296static void ar913x_ip2_handler(void) 297{ 298 ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); 299 do_IRQ(ATH79_CPU_IRQ(2)); 300} 301 302static void ar933x_ip2_handler(void) 303{ 304 ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC); 305 do_IRQ(ATH79_CPU_IRQ(2)); 306} 307 308static void ar71xx_ip3_handler(void) 309{ 310 ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); 311 do_IRQ(ATH79_CPU_IRQ(3)); 312} 313 314static void ar724x_ip3_handler(void) 315{ 316 ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); 317 do_IRQ(ATH79_CPU_IRQ(3)); 318} 319 320static void ar913x_ip3_handler(void) 321{ 322 ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); 323 do_IRQ(ATH79_CPU_IRQ(3)); 324} 325 326static void ar933x_ip3_handler(void) 327{ 328 ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); 329 do_IRQ(ATH79_CPU_IRQ(3)); 330} 331 332static void ar934x_ip3_handler(void) 333{ 334 ath79_ddr_wb_flush(AR934X_DDR_REG_FLUSH_USB); 335 do_IRQ(ATH79_CPU_IRQ(3)); 336} 337 338void __init arch_init_irq(void) 339{ 340 if (soc_is_ar71xx()) { 341 ath79_ip2_handler = ar71xx_ip2_handler; 342 ath79_ip3_handler = ar71xx_ip3_handler; 343 } else if (soc_is_ar724x()) { 344 ath79_ip2_handler = ar724x_ip2_handler; 345 ath79_ip3_handler = ar724x_ip3_handler; 346 } else if (soc_is_ar913x()) { 347 ath79_ip2_handler = ar913x_ip2_handler; 348 ath79_ip3_handler = ar913x_ip3_handler; 349 } else if (soc_is_ar933x()) { 350 ath79_ip2_handler = ar933x_ip2_handler; 351 ath79_ip3_handler = ar933x_ip3_handler; 352 } else if (soc_is_ar934x()) { 353 ath79_ip2_handler = ath79_default_ip2_handler; 354 ath79_ip3_handler = ar934x_ip3_handler; 355 } else if (soc_is_qca955x()) { 356 ath79_ip2_handler = ath79_default_ip2_handler; 357 ath79_ip3_handler = ath79_default_ip3_handler; 358 } else { 359 BUG(); 360 } 361 362 mips_cpu_irq_init(); 363 ath79_misc_irq_init(); 364 365 if (soc_is_ar934x()) 366 ar934x_ip2_irq_init(); 367 else if (soc_is_qca955x()) 368 qca955x_irq_init(); 369} 370