MIPS: Alchemy: devboard register abstraction
[linux-2.6.git] / arch / mips / alchemy / devboards / pb1200 / irqmap.c
1 /*
2  * BRIEF MODULE DESCRIPTION
3  *      Au1xxx irq map table
4  *
5  *  This program is free software; you can redistribute  it and/or modify it
6  *  under  the terms of  the GNU General  Public License as published by the
7  *  Free Software Foundation;  either version 2 of the  License, or (at your
8  *  option) any later version.
9  *
10  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
11  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
12  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
13  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
14  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
15  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
16  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
17  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
18  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
19  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20  *
21  *  You should have received a copy of the  GNU General Public License along
22  *  with this program; if not, write  to the Free Software Foundation, Inc.,
23  *  675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #include <linux/init.h>
27 #include <linux/interrupt.h>
28
29 #include <asm/mach-au1x00/au1000.h>
30
31 #ifdef CONFIG_MIPS_PB1200
32 #include <asm/mach-pb1x00/pb1200.h>
33 #endif
34
35 #ifdef CONFIG_MIPS_DB1200
36 #include <asm/mach-db1x00/db1200.h>
37 #define PB1200_INT_BEGIN DB1200_INT_BEGIN
38 #define PB1200_INT_END DB1200_INT_END
39 #endif
40
41 #include <asm/mach-db1x00/bcsr.h>
42
43 struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
44         /* This is external interrupt cascade */
45         { AU1000_GPIO_7, IRQF_TRIGGER_LOW, 0 },
46 };
47
48 static void __iomem *bcsr_virt;
49
50 /*
51  * Support for External interrupts on the Pb1200 Development platform.
52  */
53
54 static void pb1200_cascade_handler(unsigned int irq, struct irq_desc *d)
55 {
56         unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT);
57
58         for ( ; bisr; bisr &= bisr - 1)
59                 generic_handle_irq(PB1200_INT_BEGIN + __ffs(bisr));
60 }
61
62 /* NOTE: both the enable and mask bits must be cleared, otherwise the
63  * CPLD generates tons of spurious interrupts (at least on the DB1200).
64  */
65 static void pb1200_mask_irq(unsigned int irq_nr)
66 {
67         unsigned short v = 1 << (irq_nr - PB1200_INT_BEGIN);
68         __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR);
69         __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR);
70         wmb();
71 }
72
73 static void pb1200_maskack_irq(unsigned int irq_nr)
74 {
75         unsigned short v = 1 << (irq_nr - PB1200_INT_BEGIN);
76         __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR);
77         __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR);
78         __raw_writew(v, bcsr_virt + BCSR_REG_INTSTAT);  /* ack */
79         wmb();
80 }
81
82 static void pb1200_unmask_irq(unsigned int irq_nr)
83 {
84         unsigned short v = 1 << (irq_nr - PB1200_INT_BEGIN);
85         __raw_writew(v, bcsr_virt + BCSR_REG_INTSET);
86         __raw_writew(v, bcsr_virt + BCSR_REG_MASKSET);
87         wmb();
88 }
89
90 static struct irq_chip pb1200_cpld_irq_type = {
91 #ifdef CONFIG_MIPS_PB1200
92         .name = "Pb1200 Ext",
93 #endif
94 #ifdef CONFIG_MIPS_DB1200
95         .name = "Db1200 Ext",
96 #endif
97         .mask           = pb1200_mask_irq,
98         .mask_ack       = pb1200_maskack_irq,
99         .unmask         = pb1200_unmask_irq,
100 };
101
102 void __init board_init_irq(void)
103 {
104         unsigned int irq;
105
106         au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
107
108 #ifdef CONFIG_MIPS_PB1200
109         bcsr_virt = (void __iomem *)KSEG1ADDR(PB1200_BCSR_PHYS_ADDR);
110
111         /* We have a problem with CPLD rev 3. */
112         if (BCSR_WHOAMI_CPLD(bcsr_read(BCSR_WHOAMI)) <= 3) {
113                 printk(KERN_ERR "WARNING!!!\n");
114                 printk(KERN_ERR "WARNING!!!\n");
115                 printk(KERN_ERR "WARNING!!!\n");
116                 printk(KERN_ERR "WARNING!!!\n");
117                 printk(KERN_ERR "WARNING!!!\n");
118                 printk(KERN_ERR "WARNING!!!\n");
119                 printk(KERN_ERR "Pb1200 must be at CPLD rev 4. Please have Pb1200\n");
120                 printk(KERN_ERR "updated to latest revision. This software will\n");
121                 printk(KERN_ERR "not work on anything less than CPLD rev 4.\n");
122                 printk(KERN_ERR "WARNING!!!\n");
123                 printk(KERN_ERR "WARNING!!!\n");
124                 printk(KERN_ERR "WARNING!!!\n");
125                 printk(KERN_ERR "WARNING!!!\n");
126                 printk(KERN_ERR "WARNING!!!\n");
127                 printk(KERN_ERR "WARNING!!!\n");
128                 panic("Game over.  Your score is 0.");
129         }
130 #else
131         bcsr_virt = (void __iomem *)KSEG1ADDR(DB1200_BCSR_PHYS_ADDR);
132 #endif
133
134         /* mask & disable & ack all */
135         bcsr_write(BCSR_INTCLR, 0xffff);
136         bcsr_write(BCSR_MASKCLR, 0xffff);
137         bcsr_write(BCSR_INTSTAT, 0xffff);
138
139         for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++)
140                 set_irq_chip_and_handler_name(irq, &pb1200_cpld_irq_type,
141                                          handle_level_irq, "level");
142
143         set_irq_chained_handler(AU1000_GPIO_7, pb1200_cascade_handler);
144 }