diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2012-03-14 05:45:24 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2012-05-15 11:49:08 -0400 |
commit | 4dbcbdf8135def8f704b130305721bdd42a8078b (patch) | |
tree | f6b8dec7781a7ece62f55af354ba6f5e49d37fdb /arch/mips | |
parent | 5b5b544ed32a1b6ad4d7706fcee530eb67670e71 (diff) |
MIPS: ath79: rework IP2/IP3 interrupt handling
The current implementation assumes that flushing the
DDR writeback buffer is required for IP2/IP3 interrupts,
however this is not true for all SoCs.
Use SoC specific IP2/IP3 handlers instead of flushing
the buffers in the dispatcher code.
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Acked-by: Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
Cc: linux-mips@linux-mips.org
Cc: mcgrof@infradead.org
Patchwork: https://patchwork.linux-mips.org/patch/3509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/ath79/irq.c | 92 |
1 files changed, 72 insertions, 20 deletions
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 @@ | |||
1 | /* | 1 | /* |
2 | * Atheros AR71xx/AR724x/AR913x specific interrupt handling | 2 | * Atheros AR71xx/AR724x/AR913x specific interrupt handling |
3 | * | 3 | * |
4 | * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org> | 4 | * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> |
5 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | 5 | * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> |
6 | * | 6 | * |
7 | * Parts of this file are based on Atheros' 2.6.15 BSP | 7 | * Parts of this file are based on Atheros' 2.6.15 BSP |
@@ -23,8 +23,8 @@ | |||
23 | #include <asm/mach-ath79/ar71xx_regs.h> | 23 | #include <asm/mach-ath79/ar71xx_regs.h> |
24 | #include "common.h" | 24 | #include "common.h" |
25 | 25 | ||
26 | static unsigned int ath79_ip2_flush_reg; | 26 | static void (*ath79_ip2_handler)(void); |
27 | static unsigned int ath79_ip3_flush_reg; | 27 | static void (*ath79_ip3_handler)(void); |
28 | 28 | ||
29 | static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) | 29 | static void ath79_misc_irq_handler(unsigned int irq, struct irq_desc *desc) |
30 | { | 30 | { |
@@ -152,10 +152,8 @@ asmlinkage void plat_irq_dispatch(void) | |||
152 | if (pending & STATUSF_IP7) | 152 | if (pending & STATUSF_IP7) |
153 | do_IRQ(ATH79_CPU_IRQ_TIMER); | 153 | do_IRQ(ATH79_CPU_IRQ_TIMER); |
154 | 154 | ||
155 | else if (pending & STATUSF_IP2) { | 155 | else if (pending & STATUSF_IP2) |
156 | ath79_ddr_wb_flush(ath79_ip2_flush_reg); | 156 | ath79_ip2_handler(); |
157 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
158 | } | ||
159 | 157 | ||
160 | else if (pending & STATUSF_IP4) | 158 | else if (pending & STATUSF_IP4) |
161 | do_IRQ(ATH79_CPU_IRQ_GE0); | 159 | do_IRQ(ATH79_CPU_IRQ_GE0); |
@@ -163,10 +161,8 @@ asmlinkage void plat_irq_dispatch(void) | |||
163 | else if (pending & STATUSF_IP5) | 161 | else if (pending & STATUSF_IP5) |
164 | do_IRQ(ATH79_CPU_IRQ_GE1); | 162 | do_IRQ(ATH79_CPU_IRQ_GE1); |
165 | 163 | ||
166 | else if (pending & STATUSF_IP3) { | 164 | else if (pending & STATUSF_IP3) |
167 | ath79_ddr_wb_flush(ath79_ip3_flush_reg); | 165 | ath79_ip3_handler(); |
168 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
169 | } | ||
170 | 166 | ||
171 | else if (pending & STATUSF_IP6) | 167 | else if (pending & STATUSF_IP6) |
172 | do_IRQ(ATH79_CPU_IRQ_MISC); | 168 | do_IRQ(ATH79_CPU_IRQ_MISC); |
@@ -175,22 +171,78 @@ asmlinkage void plat_irq_dispatch(void) | |||
175 | spurious_interrupt(); | 171 | spurious_interrupt(); |
176 | } | 172 | } |
177 | 173 | ||
174 | /* | ||
175 | * The IP2/IP3 lines are tied to a PCI/WMAC/USB device. Drivers for | ||
176 | * these devices typically allocate coherent DMA memory, however the | ||
177 | * DMA controller may still have some unsynchronized data in the FIFO. | ||
178 | * Issue a flush in the handlers to ensure that the driver sees | ||
179 | * the update. | ||
180 | */ | ||
181 | static void ar71xx_ip2_handler(void) | ||
182 | { | ||
183 | ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_PCI); | ||
184 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
185 | } | ||
186 | |||
187 | static void ar724x_ip2_handler(void) | ||
188 | { | ||
189 | ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_PCIE); | ||
190 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
191 | } | ||
192 | |||
193 | static void ar913x_ip2_handler(void) | ||
194 | { | ||
195 | ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_WMAC); | ||
196 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
197 | } | ||
198 | |||
199 | static void ar933x_ip2_handler(void) | ||
200 | { | ||
201 | ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_WMAC); | ||
202 | do_IRQ(ATH79_CPU_IRQ_IP2); | ||
203 | } | ||
204 | |||
205 | static void ar71xx_ip3_handler(void) | ||
206 | { | ||
207 | ath79_ddr_wb_flush(AR71XX_DDR_REG_FLUSH_USB); | ||
208 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
209 | } | ||
210 | |||
211 | static void ar724x_ip3_handler(void) | ||
212 | { | ||
213 | ath79_ddr_wb_flush(AR724X_DDR_REG_FLUSH_USB); | ||
214 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
215 | } | ||
216 | |||
217 | static void ar913x_ip3_handler(void) | ||
218 | { | ||
219 | ath79_ddr_wb_flush(AR913X_DDR_REG_FLUSH_USB); | ||
220 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
221 | } | ||
222 | |||
223 | static void ar933x_ip3_handler(void) | ||
224 | { | ||
225 | ath79_ddr_wb_flush(AR933X_DDR_REG_FLUSH_USB); | ||
226 | do_IRQ(ATH79_CPU_IRQ_USB); | ||
227 | } | ||
228 | |||
178 | void __init arch_init_irq(void) | 229 | void __init arch_init_irq(void) |
179 | { | 230 | { |
180 | if (soc_is_ar71xx()) { | 231 | if (soc_is_ar71xx()) { |
181 | ath79_ip2_flush_reg = AR71XX_DDR_REG_FLUSH_PCI; | 232 | ath79_ip2_handler = ar71xx_ip2_handler; |
182 | ath79_ip3_flush_reg = AR71XX_DDR_REG_FLUSH_USB; | 233 | ath79_ip3_handler = ar71xx_ip3_handler; |
183 | } else if (soc_is_ar724x()) { | 234 | } else if (soc_is_ar724x()) { |
184 | ath79_ip2_flush_reg = AR724X_DDR_REG_FLUSH_PCIE; | 235 | ath79_ip2_handler = ar724x_ip2_handler; |
185 | ath79_ip3_flush_reg = AR724X_DDR_REG_FLUSH_USB; | 236 | ath79_ip3_handler = ar724x_ip3_handler; |
186 | } else if (soc_is_ar913x()) { | 237 | } else if (soc_is_ar913x()) { |
187 | ath79_ip2_flush_reg = AR913X_DDR_REG_FLUSH_WMAC; | 238 | ath79_ip2_handler = ar913x_ip2_handler; |
188 | ath79_ip3_flush_reg = AR913X_DDR_REG_FLUSH_USB; | 239 | ath79_ip3_handler = ar913x_ip3_handler; |
189 | } else if (soc_is_ar933x()) { | 240 | } else if (soc_is_ar933x()) { |
190 | ath79_ip2_flush_reg = AR933X_DDR_REG_FLUSH_WMAC; | 241 | ath79_ip2_handler = ar933x_ip2_handler; |
191 | ath79_ip3_flush_reg = AR933X_DDR_REG_FLUSH_USB; | 242 | ath79_ip3_handler = ar933x_ip3_handler; |
192 | } else | 243 | } else { |
193 | BUG(); | 244 | BUG(); |
245 | } | ||
194 | 246 | ||
195 | cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; | 247 | cp0_perfcount_irq = ATH79_MISC_IRQ_PERFC; |
196 | mips_cpu_irq_init(); | 248 | mips_cpu_irq_init(); |