X-Git-Url: http://git.cascardo.info/?a=blobdiff_plain;f=arch%2Fmips%2Fath79%2Firq.c;fp=arch%2Fmips%2Fath79%2Firq.c;h=9f87ade52956d675be614604f9936e32ecac773b;hb=4dbcbdf8135def8f704b130305721bdd42a8078b;hp=1b073de44680ea0fdba8c95f84cf6f214f394448;hpb=5b5b544ed32a1b6ad4d7706fcee530eb67670e71;p=cascardo%2Flinux.git diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 1b073de44680..9f87ade52956 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c @@ -1,7 +1,7 @@ /* * Atheros AR71xx/AR724x/AR913x specific interrupt handling * - * Copyright (C) 2008-2010 Gabor Juhos + * Copyright (C) 2008-2011 Gabor Juhos * Copyright (C) 2008 Imre Kaloz * * Parts of this file are based on Atheros' 2.6.15 BSP @@ -23,8 +23,8 @@ #include #include "common.h" -static unsigned int ath79_ip2_flush_reg; -static unsigned int ath79_ip3_flush_reg; +static void (*ath79_ip2_handler)(void); +static void (*ath79_ip3_handler)(void); static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) { @@ -152,10 +152,8 @@ asmlinkage void plat_irq_dispatch(void) if (pending & STATUSF_IP7) do_IRQ(ATH79_CPU_IRQ_TIMER); - else if (pending & STATUSF_IP2) { - ath79_ddr_wb_flush(ath79_ip2_flush_reg); - do_IRQ(ATH79_CPU_IRQ_IP2); - } + else if (pending & STATUSF_IP2) + ath79_ip2_handler(); else if (pending & STATUSF_IP4) do_IRQ(ATH79_CPU_IRQ_GE0); @@ -163,10 +161,8 @@ asmlinkage void plat_irq_dispatch(void) else if (pending & STATUSF_IP5) do_IRQ(ATH79_CPU_IRQ_GE1); - else if (pending & STATUSF_IP3) { - ath79_ddr_wb_flush(ath79_ip3_flush_reg); - do_IRQ(ATH79_CPU_IRQ_USB); - } + else if (pending & STATUSF_IP3) + ath79_ip3_handler(); else if (pending & STATUSF_IP6) do_IRQ(ATH79_CPU_IRQ_MISC); @@ -175,22 +171,78 @@ asmlinkage void plat_irq_dispatch(void) spurious_interrupt(); } +/* + * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for + * these devices typically allocate coherent DMA memory, however the + * DMA controller may still have some unsynchronized data in the FIFO. + * Issue a flush in the handlers to ensure that the driver sees + * the update. + */ +static void ar71xx_ip2_handler(void) +{ + ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); + do_IRQ(ATH79_CPU_IRQ_IP2); +} + +static void ar724x_ip2_handler(void) +{ + ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); + do_IRQ(ATH79_CPU_IRQ_IP2); +} + +static void ar913x_ip2_handler(void) +{ + ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); + do_IRQ(ATH79_CPU_IRQ_IP2); +} + +static void ar933x_ip2_handler(void) +{ + ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC); + do_IRQ(ATH79_CPU_IRQ_IP2); +} + +static void ar71xx_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + +static void ar724x_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + +static void ar913x_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + +static void ar933x_ip3_handler(void) +{ + ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); + do_IRQ(ATH79_CPU_IRQ_USB); +} + void __init arch_init_irq(void) { if (soc_is_ar71xx()) { - ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI; - ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB; + ath79_ip2_handler = ar71xx_ip2_handler; + ath79_ip3_handler = ar71xx_ip3_handler; } else if (soc_is_ar724x()) { - ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE; - ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB; + ath79_ip2_handler = ar724x_ip2_handler; + ath79_ip3_handler = ar724x_ip3_handler; } else if (soc_is_ar913x()) { - ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC; - ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB; + ath79_ip2_handler = ar913x_ip2_handler; + ath79_ip3_handler = ar913x_ip3_handler; } else if (soc_is_ar933x()) { - ath79_ip2_flush_reg = AR933X_DDR_REG_FLUSH_WMAC; - ath79_ip3_flush_reg = AR933X_DDR_REG_FLUSH_USB; - } else + ath79_ip2_handler = ar933x_ip2_handler; + ath79_ip3_handler = ar933x_ip3_handler; + } else { BUG(); + } cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; mips_cpu_irq_init();