Commit | Line | Data |
---|---|---|
81ffb18c AB |
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 | } |