ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / arm / mach-iop3xx / iop310-irq.c
1 /*
2  * linux/arch/arm/mach-iop3xx/iop310-irq.c
3  *
4  * Generic IOP310 IRQ handling functionality
5  *
6  * Author:  Nicolas Pitre
7  * Copyright:   (C) 2001 MontaVista Software Inc.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  *
13  * Added IOP310 chipset and IQ80310 board demuxing, masking code. - DS
14  *
15  */
16 #include <linux/init.h>
17 #include <linux/interrupt.h>
18 #include <linux/list.h>
19
20 #include <asm/mach/irq.h>
21 #include <asm/irq.h>
22 #include <asm/hardware.h>
23
24 #include <asm/mach-types.h>
25
26 extern void xs80200_irq_mask(unsigned int);
27 extern void xs80200_irq_unmask(unsigned int);
28 extern void xs80200_init_irq(void);
29
30 extern void do_IRQ(int, struct pt_regs *);
31
32 static u32 iop310_mask /* = 0 */;
33
34 static void iop310_irq_mask (unsigned int irq)
35 {
36         iop310_mask ++;
37
38         /*
39          * No mask bits on the 80312, so we have to
40          * mask everything from the outside!
41          */
42         if (iop310_mask == 1) {
43                 disable_irq(IRQ_XS80200_EXTIRQ);
44                 irq_desc[IRQ_XS80200_EXTIRQ].chip->mask(IRQ_XS80200_EXTIRQ);
45         }
46 }
47
48 static void iop310_irq_unmask (unsigned int irq)
49 {
50         if (iop310_mask)
51                 iop310_mask --;
52
53         /*
54          * Check if all 80312 sources are unmasked now
55          */
56         if (iop310_mask == 0)
57                 enable_irq(IRQ_XS80200_EXTIRQ);
58 }
59
60 struct irqchip ext_chip = {
61         .ack    = iop310_irq_mask,
62         .mask   = iop310_irq_mask,
63         .unmask = iop310_irq_unmask,
64 };
65
66 void
67 iop310_irq_demux(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
68 {
69         u32 fiq1isr = *((volatile u32*)IOP310_FIQ1ISR);
70         u32 fiq2isr = *((volatile u32*)IOP310_FIQ2ISR);
71         struct irqdesc *d;
72         unsigned int irqno = 0;
73
74         if(fiq1isr)
75         {
76                 if(fiq1isr & 0x1)
77                         irqno = IRQ_IOP310_DMA0;
78                 if(fiq1isr & 0x2)
79                         irqno = IRQ_IOP310_DMA1;
80                 if(fiq1isr & 0x4)
81                         irqno = IRQ_IOP310_DMA2;
82                 if(fiq1isr & 0x10)
83                         irqno = IRQ_IOP310_PMON;
84                 if(fiq1isr & 0x20)
85                         irqno = IRQ_IOP310_AAU;
86         }
87         else
88         {
89                 if(fiq2isr & 0x2)
90                         irqno = IRQ_IOP310_I2C;
91                 if(fiq2isr & 0x4)
92                         irqno = IRQ_IOP310_MU;
93         }
94
95         if (irqno) {
96                 d = irq_desc + irqno;
97                 d->handle(irqno, d, regs);
98         }
99 }
100
101 void __init iop310_init_irq(void)
102 {
103         unsigned int i;
104
105         for(i = IOP310_IRQ_OFS; i < NR_IOP310_IRQS; i++)
106         {
107                 set_irq_chip(i, &ext_chip);
108                 set_irq_handler(i, do_level_IRQ);
109                 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
110         }
111
112         xs80200_init_irq();
113 }