[amazon] Apply patch 200-fix_deprecated_interrupt_definations.patch directly
[openwrt-10.03/.git] / target / linux / amazon / files / arch / mips / amazon / interrupt.c
1 /*
2  *  Gary Jennejohn (C) 2003 <gj@denx.de>
3  *  Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
4  *  Copyright (C) 2007 John Crispin <blogic@openwrt.org>
5  *
6  *  This program is free software; you can distribute it and/or modify it
7  *  under the terms of the GNU General Public License (Version 2) as
8  *  published by the Free Software Foundation.
9  *
10  *  This program is distributed in the hope it will be useful, but WITHOUT
11  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  *  for more details.
14  *
15  *  You should have received a copy of the GNU General Public License along
16  *  with this program; if not, write to the Free Software Foundation, Inc.,
17  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
18  *
19  * Routines for generic manipulation of the interrupts found on the 
20  * AMAZON boards.
21  */
22
23 #include <linux/init.h>
24 #include <linux/sched.h>
25 #include <linux/slab.h>
26 #include <linux/interrupt.h>
27 #include <linux/kernel_stat.h>
28 #include <linux/module.h>
29
30 #include <asm/amazon/amazon.h>
31 #include <asm/amazon/irq.h>
32 #include <asm/bootinfo.h>
33 #include <asm/irq_cpu.h>
34 #include <asm/irq.h>
35 #include <asm/time.h>
36
37 static void amazon_disable_irq(unsigned int irq_nr)
38 {
39         int i;
40         u32 amazon_ier = AMAZON_ICU_IM0_IER;
41
42         if (irq_nr <= INT_NUM_IM0_IRL11 && irq_nr >= INT_NUM_IM0_IRL0)
43                 amazon_writel(amazon_readl(amazon_ier) & (~(AMAZON_DMA_H_MASK)), amazon_ier);
44         else {
45                 irq_nr -= INT_NUM_IRQ0;
46                 for (i = 0; i <= 4; i++)
47                 {
48                         if (irq_nr <= 31) 
49                         amazon_writel(amazon_readl(amazon_ier) & ~(1 << irq_nr ), amazon_ier);
50                         amazon_ier += 0x10;
51                         irq_nr -= 32;
52                 }
53         }       
54 }
55
56 static void amazon_mask_and_ack_irq(unsigned int irq_nr)
57 {
58         int i;
59         u32 amazon_ier = AMAZON_ICU_IM0_IER;
60         u32 amazon_isr = AMAZON_ICU_IM0_ISR;
61
62         if (irq_nr <= INT_NUM_IM0_IRL11 && irq_nr >= INT_NUM_IM0_IRL0){
63                 amazon_writel(amazon_readl(amazon_ier) & (~(AMAZON_DMA_H_MASK)), amazon_ier);
64                 amazon_writel(AMAZON_DMA_H_MASK, amazon_isr); 
65         } else {
66                 irq_nr -= INT_NUM_IRQ0;
67                 for (i = 0; i <= 4; i++)
68                 {
69                         if (irq_nr <= 31){ 
70                         amazon_writel(amazon_readl(amazon_ier) & ~(1 << irq_nr ), amazon_ier);
71                                 amazon_writel((1 << irq_nr ), amazon_isr);
72                         }
73                         amazon_ier += 0x10;
74                         amazon_isr += 0x10;
75                         irq_nr -= 32;
76                 }
77         }
78 }
79
80 static void amazon_enable_irq(unsigned int irq_nr)
81 {
82         int i;
83         u32 amazon_ier = AMAZON_ICU_IM0_IER;
84
85         if (irq_nr <= INT_NUM_IM0_IRL11 && irq_nr >= INT_NUM_IM0_IRL0)
86                 amazon_writel(amazon_readl(amazon_ier) | AMAZON_DMA_H_MASK, amazon_ier);
87         else {
88                 irq_nr -= INT_NUM_IRQ0;
89                 for (i = 0; i <= 4; i++)
90                 {
91                         if (irq_nr <= 31)
92                                 amazon_writel(amazon_readl(amazon_ier) | (1 << irq_nr ), amazon_ier);
93                         amazon_ier += 0x10;
94                         irq_nr -= 32;
95                 }
96         }
97 }
98
99 static unsigned int amazon_startup_irq(unsigned int irq)
100 {
101         amazon_enable_irq(irq);
102         return 0;
103 }
104
105 static void amazon_end_irq(unsigned int irq)
106 {
107         if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
108                 amazon_enable_irq(irq);
109         }
110 }
111
112 static struct hw_interrupt_type amazon_irq_type = {
113         "AMAZON",
114         .startup = amazon_startup_irq,
115         .enable = amazon_enable_irq,
116         .disable = amazon_disable_irq,
117         .unmask = amazon_enable_irq,
118         .ack = amazon_mask_and_ack_irq,
119         .mask = amazon_disable_irq,
120         .mask_ack = amazon_mask_and_ack_irq,
121         .end = amazon_end_irq
122 };
123
124 /* Cascaded interrupts from IM0-4 */
125 static inline void amazon_hw_irqdispatch(u8 line)
126 {
127         u32 irq;
128
129         irq = (amazon_readl(AMAZON_ICU_IM_VEC) >> (line * 5)) & AMAZON_ICU_IM0_VEC_MASK;
130         if (line == 0 && irq <= 11 && irq >= 0) {
131                 //DMA fixed to IM0_IRL0
132                 irq = 0;
133         }
134         do_IRQ(irq + INT_NUM_IRQ0 + (line * 32));
135 }
136
137 asmlinkage void plat_irq_dispatch(void)
138 {
139         unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
140         if (pending & CAUSEF_IP7){
141                 do_IRQ(MIPS_CPU_TIMER_IRQ);
142                 goto out;
143         } else {
144                 unsigned int i;
145                 for (i = 0; i <= 4; i++)
146                 {
147                         if(pending & (CAUSEF_IP2 << i)){
148                                 amazon_hw_irqdispatch(i);
149                                 goto out;
150                         }
151                 }
152         }
153         printk("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
154 out:
155         return;
156 }
157
158 static struct irqaction cascade = {
159         .handler        = no_action,
160         .flags          = IRQF_DISABLED,
161         .name           = "cascade",
162 };
163
164 void __init arch_init_irq(void)
165 {
166         int i;
167
168         /* mask all interrupt sources */
169         for(i = 0; i <= 4; i++){
170                 amazon_writel(0, AMAZON_ICU_IM0_IER + (i * 0x10));
171         }
172
173         mips_cpu_irq_init();
174
175         /* set up irq cascade */
176         for (i = 2; i <= 6; i++) {
177                 setup_irq(i, &cascade);
178         }
179
180         for (i = INT_NUM_IRQ0; i <= INT_NUM_IM4_IRL31; i++) {
181                 irq_desc[i].status      = IRQ_DISABLED;
182                 irq_desc[i].action      = 0;
183                 irq_desc[i].depth       = 1;
184                 set_irq_chip(i, &amazon_irq_type);
185         }
186 }