source: trunk/target/linux/ar71xx/files/arch/mips/ar71xx/irq.c @ 20280

Last change on this file since 20280 was 20280, checked in by juhosg, 7 years ago

ar71xx: use set_irq_chained_handler for the PCI IRQs

  • Property svn:eol-style set to native
File size: 9.5 KB
Line 
1/*
2 *  Atheros AR71xx SoC specific interrupt handling
3 *
4 *  Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
5 *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6 *
7 *  Parts of this file are based on Atheros' 2.6.15 BSP
8 *
9 *  This program is free software; you can redistribute it and/or modify it
10 *  under the terms of the GNU General Public License version 2 as published
11 *  by the Free Software Foundation.
12 */
13
14#include <linux/kernel.h>
15#include <linux/init.h>
16#include <linux/interrupt.h>
17#include <linux/irq.h>
18
19#include <asm/irq_cpu.h>
20#include <asm/mipsregs.h>
21
22#include <asm/mach-ar71xx/ar71xx.h>
23
24#ifdef CONFIG_PCI
25static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
26{
27        u32 pending;
28
29        pending = ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_STATUS) &
30                  ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE);
31
32        if (pending & PCI_INT_DEV0)
33                generic_handle_irq(AR71XX_PCI_IRQ_DEV0);
34
35        else if (pending & PCI_INT_DEV1)
36                generic_handle_irq(AR71XX_PCI_IRQ_DEV1);
37
38        else if (pending & PCI_INT_DEV2)
39                generic_handle_irq(AR71XX_PCI_IRQ_DEV2);
40
41        else if (pending & PCI_INT_CORE)
42                generic_handle_irq(AR71XX_PCI_IRQ_CORE);
43
44        else
45                spurious_interrupt();
46}
47
48static void ar71xx_pci_irq_unmask(unsigned int irq)
49{
50        irq -= AR71XX_PCI_IRQ_BASE;
51        ar71xx_reset_wr(AR71XX_RESET_REG_PCI_INT_ENABLE,
52                ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE) | (1 << irq));
53
54        /* flush write */
55        ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE);
56}
57
58static void ar71xx_pci_irq_mask(unsigned int irq)
59{
60        irq -= AR71XX_PCI_IRQ_BASE;
61        ar71xx_reset_wr(AR71XX_RESET_REG_PCI_INT_ENABLE,
62                ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE) & ~(1 << irq));
63
64        /* flush write */
65        ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE);
66}
67
68static struct irq_chip ar71xx_pci_irq_chip = {
69        .name           = "AR71XX PCI ",
70        .mask           = ar71xx_pci_irq_mask,
71        .unmask         = ar71xx_pci_irq_unmask,
72        .mask_ack       = ar71xx_pci_irq_mask,
73};
74
75static void __init ar71xx_pci_irq_init(void)
76{
77        int i;
78
79        ar71xx_reset_wr(AR71XX_RESET_REG_PCI_INT_ENABLE, 0);
80        ar71xx_reset_wr(AR71XX_RESET_REG_PCI_INT_STATUS, 0);
81
82        for (i = AR71XX_PCI_IRQ_BASE;
83             i < AR71XX_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) {
84                irq_desc[i].status = IRQ_DISABLED;
85                set_irq_chip_and_handler(i, &ar71xx_pci_irq_chip,
86                                         handle_level_irq);
87        }
88
89        set_irq_chained_handler(AR71XX_CPU_IRQ_IP2, ar71xx_pci_irq_handler);
90}
91
92static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
93{
94        u32 pending;
95
96        pending = ar724x_pci_rr(AR724X_PCI_REG_INT_STATUS) &
97                  ar724x_pci_rr(AR724X_PCI_REG_INT_MASK);
98
99        if (pending & AR724X_PCI_INT_DEV0)
100                generic_handle_irq(AR71XX_PCI_IRQ_DEV0);
101
102        else
103                spurious_interrupt();
104}
105
106static void ar724x_pci_irq_unmask(unsigned int irq)
107{
108        switch (irq) {
109        case AR71XX_PCI_IRQ_DEV0:
110                irq -= AR71XX_PCI_IRQ_BASE;
111                ar724x_pci_wr(AR724X_PCI_REG_INT_MASK,
112                              ar724x_pci_rr(AR724X_PCI_REG_INT_MASK) |
113                                            AR724X_PCI_INT_DEV0);
114                /* flush write */
115                ar724x_pci_rr(AR724X_PCI_REG_INT_MASK);
116        }
117}
118
119static void ar724x_pci_irq_mask(unsigned int irq)
120{
121        switch (irq) {
122        case AR71XX_PCI_IRQ_DEV0:
123                irq -= AR71XX_PCI_IRQ_BASE;
124                ar724x_pci_wr(AR724X_PCI_REG_INT_MASK,
125                              ar724x_pci_rr(AR724X_PCI_REG_INT_MASK) &
126                                            ~AR724X_PCI_INT_DEV0);
127                /* flush write */
128                ar724x_pci_rr(AR724X_PCI_REG_INT_MASK);
129
130                ar724x_pci_wr(AR724X_PCI_REG_INT_STATUS,
131                              ar724x_pci_rr(AR724X_PCI_REG_INT_STATUS) |
132                                            AR724X_PCI_INT_DEV0);
133                /* flush write */
134                ar724x_pci_rr(AR724X_PCI_REG_INT_STATUS);
135        }
136}
137
138static struct irq_chip ar724x_pci_irq_chip = {
139        .name           = "AR724X PCI ",
140        .mask           = ar724x_pci_irq_mask,
141        .unmask         = ar724x_pci_irq_unmask,
142        .mask_ack       = ar724x_pci_irq_mask,
143};
144
145static void __init ar724x_pci_irq_init(void)
146{
147        u32 t;
148        int i;
149
150        t = ar71xx_reset_rr(AR724X_RESET_REG_RESET_MODULE);
151        if (t & (AR724X_RESET_PCIE | AR724X_RESET_PCIE_PHY |
152                 AR724X_RESET_PCIE_PHY_SERIAL)) {
153                return;
154        }
155
156        ar724x_pci_wr(AR724X_PCI_REG_INT_MASK, 0);
157        ar724x_pci_wr(AR724X_PCI_REG_INT_STATUS, 0);
158
159        for (i = AR71XX_PCI_IRQ_BASE;
160             i < AR71XX_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) {
161                irq_desc[i].status = IRQ_DISABLED;
162                set_irq_chip_and_handler(i, &ar724x_pci_irq_chip,
163                                         handle_level_irq);
164        }
165
166        set_irq_chained_handler(AR71XX_CPU_IRQ_IP2, ar724x_pci_irq_handler);
167}
168#else
169static inline void ar71xx_pci_irq_init(void) {};
170static inline void ar724x_pci_irq_init(void) {};
171#endif /* CONFIG_PCI */
172
173static void ar71xx_gpio_irq_dispatch(void)
174{
175        u32 pending;
176
177        pending = ar71xx_gpio_rr(GPIO_REG_INT_PENDING)
178                & ar71xx_gpio_rr(GPIO_REG_INT_ENABLE);
179
180        if (pending)
181                do_IRQ(AR71XX_GPIO_IRQ_BASE + fls(pending) - 1);
182        else
183                spurious_interrupt();
184}
185
186static void ar71xx_gpio_irq_unmask(unsigned int irq)
187{
188        irq -= AR71XX_GPIO_IRQ_BASE;
189        ar71xx_gpio_wr(GPIO_REG_INT_ENABLE,
190                        ar71xx_gpio_rr(GPIO_REG_INT_ENABLE) | (1 << irq));
191
192        /* flush write */
193        ar71xx_gpio_rr(GPIO_REG_INT_ENABLE);
194}
195
196static void ar71xx_gpio_irq_mask(unsigned int irq)
197{
198        irq -= AR71XX_GPIO_IRQ_BASE;
199        ar71xx_gpio_wr(GPIO_REG_INT_ENABLE,
200                        ar71xx_gpio_rr(GPIO_REG_INT_ENABLE) & ~(1 << irq));
201
202        /* flush write */
203        ar71xx_gpio_rr(GPIO_REG_INT_ENABLE);
204}
205
206#if 0
207static int ar71xx_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
208{
209        /* TODO: implement */
210        return 0;
211}
212#else
213#define ar71xx_gpio_irq_set_type        NULL
214#endif
215
216static struct irq_chip ar71xx_gpio_irq_chip = {
217        .name           = "AR71XX GPIO",
218        .unmask         = ar71xx_gpio_irq_unmask,
219        .mask           = ar71xx_gpio_irq_mask,
220        .mask_ack       = ar71xx_gpio_irq_mask,
221        .set_type       = ar71xx_gpio_irq_set_type,
222};
223
224static struct irqaction ar71xx_gpio_irqaction = {
225        .handler        = no_action,
226        .name           = "cascade [AR71XX GPIO]",
227};
228
229#define GPIO_IRQ_INIT_STATUS (IRQ_LEVEL | IRQ_TYPE_LEVEL_HIGH | IRQ_DISABLED)
230#define GPIO_INT_ALL    0xffff
231
232static void __init ar71xx_gpio_irq_init(void)
233{
234        int i;
235
236        ar71xx_gpio_wr(GPIO_REG_INT_ENABLE, 0);
237        ar71xx_gpio_wr(GPIO_REG_INT_PENDING, 0);
238
239        /* setup type of all GPIO interrupts to level sensitive */
240        ar71xx_gpio_wr(GPIO_REG_INT_TYPE, GPIO_INT_ALL);
241
242        /* setup polarity of all GPIO interrupts to active high */
243        ar71xx_gpio_wr(GPIO_REG_INT_POLARITY, GPIO_INT_ALL);
244
245        for (i = AR71XX_GPIO_IRQ_BASE;
246             i < AR71XX_GPIO_IRQ_BASE + AR71XX_GPIO_IRQ_COUNT; i++) {
247                irq_desc[i].status = GPIO_IRQ_INIT_STATUS;
248                set_irq_chip_and_handler(i, &ar71xx_gpio_irq_chip,
249                                         handle_level_irq);
250        }
251
252        setup_irq(AR71XX_MISC_IRQ_GPIO, &ar71xx_gpio_irqaction);
253}
254
255static void ar71xx_misc_irq_dispatch(void)
256{
257        u32 pending;
258
259        pending = ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_STATUS)
260            & ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
261
262        if (pending & MISC_INT_UART)
263                do_IRQ(AR71XX_MISC_IRQ_UART);
264
265        else if (pending & MISC_INT_DMA)
266                do_IRQ(AR71XX_MISC_IRQ_DMA);
267
268        else if (pending & MISC_INT_PERFC)
269                do_IRQ(AR71XX_MISC_IRQ_PERFC);
270
271        else if (pending & MISC_INT_TIMER)
272                do_IRQ(AR71XX_MISC_IRQ_TIMER);
273
274        else if (pending & MISC_INT_OHCI)
275                do_IRQ(AR71XX_MISC_IRQ_OHCI);
276
277        else if (pending & MISC_INT_ERROR)
278                do_IRQ(AR71XX_MISC_IRQ_ERROR);
279
280        else if (pending & MISC_INT_GPIO)
281                ar71xx_gpio_irq_dispatch();
282
283        else if (pending & MISC_INT_WDOG)
284                do_IRQ(AR71XX_MISC_IRQ_WDOG);
285
286        else
287                spurious_interrupt();
288}
289
290static void ar71xx_misc_irq_unmask(unsigned int irq)
291{
292        irq -= AR71XX_MISC_IRQ_BASE;
293        ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE,
294                ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE) | (1 << irq));
295
296        /* flush write */
297        ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
298}
299
300static void ar71xx_misc_irq_mask(unsigned int irq)
301{
302        irq -= AR71XX_MISC_IRQ_BASE;
303        ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE,
304                ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE) & ~(1 << irq));
305
306        /* flush write */
307        ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
308}
309
310static void ar724x_misc_irq_ack(unsigned int irq)
311{
312        irq -= AR71XX_MISC_IRQ_BASE;
313        ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_STATUS,
314                ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_STATUS) & ~(1 << irq));
315
316        /* flush write */
317        ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_STATUS);
318}
319
320static struct irq_chip ar71xx_misc_irq_chip = {
321        .name           = "AR71XX MISC",
322        .unmask         = ar71xx_misc_irq_unmask,
323        .mask           = ar71xx_misc_irq_mask,
324};
325
326static struct irqaction ar71xx_misc_irqaction = {
327        .handler        = no_action,
328        .name           = "cascade [AR71XX MISC]",
329};
330
331static void __init ar71xx_misc_irq_init(void)
332{
333        int i;
334
335        ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE, 0);
336        ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_STATUS, 0);
337
338        if (ar71xx_soc == AR71XX_SOC_AR7240)
339                ar71xx_misc_irq_chip.ack = ar724x_misc_irq_ack;
340        else
341                ar71xx_misc_irq_chip.mask_ack = ar71xx_misc_irq_mask;
342
343        for (i = AR71XX_MISC_IRQ_BASE;
344             i < AR71XX_MISC_IRQ_BASE + AR71XX_MISC_IRQ_COUNT; i++) {
345                irq_desc[i].status = IRQ_DISABLED;
346                set_irq_chip_and_handler(i, &ar71xx_misc_irq_chip,
347                                         handle_level_irq);
348        }
349
350        setup_irq(AR71XX_CPU_IRQ_MISC, &ar71xx_misc_irqaction);
351}
352
353asmlinkage void plat_irq_dispatch(void)
354{
355        unsigned long pending;
356
357        pending = read_c0_status() & read_c0_cause() & ST0_IM;
358
359        if (pending & STATUSF_IP7)
360                do_IRQ(AR71XX_CPU_IRQ_TIMER);
361
362        else if (pending & STATUSF_IP2)
363                do_IRQ(AR71XX_CPU_IRQ_IP2);
364
365        else if (pending & STATUSF_IP4)
366                do_IRQ(AR71XX_CPU_IRQ_GE0);
367
368        else if (pending & STATUSF_IP5)
369                do_IRQ(AR71XX_CPU_IRQ_GE1);
370
371        else if (pending & STATUSF_IP3)
372                do_IRQ(AR71XX_CPU_IRQ_USB);
373
374        else if (pending & STATUSF_IP6)
375                ar71xx_misc_irq_dispatch();
376
377        else
378                spurious_interrupt();
379}
380
381void __init arch_init_irq(void)
382{
383        mips_cpu_irq_init();
384
385        ar71xx_misc_irq_init();
386
387        cp0_perfcount_irq = AR71XX_MISC_IRQ_PERFC;
388
389        switch (ar71xx_soc) {
390        case AR71XX_SOC_AR7130:
391        case AR71XX_SOC_AR7141:
392        case AR71XX_SOC_AR7161:
393                ar71xx_pci_irq_init();
394                break;
395        case AR71XX_SOC_AR7240:
396                ar724x_pci_irq_init();
397                break;
398        default:
399                break;
400        }
401
402        ar71xx_gpio_irq_init();
403}
Note: See TracBrowser for help on using the repository browser.