2 * Gary Jennejohn (C) 2003 <gj@denx.de>
3 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
5 * This program is free software; you can distribute it and/or modify it
6 * under the terms of the GNU General Public License (Version 2) as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
18 * Routines for generic manipulation of the interrupts found on the
22 #include <linux/init.h>
23 #include <linux/sched.h>
24 #include <linux/slab.h>
25 #include <linux/interrupt.h>
26 #include <linux/kernel_stat.h>
27 #include <linux/module.h>
29 #include <asm/amazon/amazon.h>
30 #include <asm/amazon/irq.h>
31 #include <asm/bootinfo.h>
32 #include <asm/irq_cpu.h>
36 static void amazon_disable_irq(unsigned int irq_nr
)
38 /* have to access the correct register here */
39 if (irq_nr
<= INT_NUM_IM0_IRL11
&& irq_nr
>= INT_NUM_IM0_IRL0
)
40 /* access IM0 DMA channels */
41 *AMAZON_ICU_IM0_IER
&= (~(AMAZON_DMA_H_MASK
));
42 else if (irq_nr
<= INT_NUM_IM0_IRL31
&& irq_nr
>= INT_NUM_IM0_IRL12
)
43 /* access IM0 except DMA*/
44 *AMAZON_ICU_IM0_IER
&= (~AMAZON_ICU_IM0_IER_IR(irq_nr
));
45 else if (irq_nr
<= INT_NUM_IM1_IRL31
&& irq_nr
>= INT_NUM_IM1_IRL0
)
47 *AMAZON_ICU_IM1_IER
&= (~AMAZON_ICU_IM1_IER_IR(irq_nr
- INT_NUM_IM1_IRL0
));
48 else if (irq_nr
<= INT_NUM_IM2_IRL31
&& irq_nr
>= INT_NUM_IM2_IRL0
)
50 *AMAZON_ICU_IM2_IER
&= (~AMAZON_ICU_IM2_IER_IR(irq_nr
- INT_NUM_IM2_IRL0
));
51 else if (irq_nr
<= INT_NUM_IM3_IRL31
&& irq_nr
>= INT_NUM_IM3_IRL0
)
53 *AMAZON_ICU_IM3_IER
&= (~AMAZON_ICU_IM3_IER_IR((irq_nr
- INT_NUM_IM3_IRL0
)));
54 else if (irq_nr
<= INT_NUM_IM4_IRL31
&& irq_nr
>= INT_NUM_IM4_IRL0
)
56 *AMAZON_ICU_IM4_IER
&= (~AMAZON_ICU_IM4_IER_IR((irq_nr
- INT_NUM_IM4_IRL0
)));
59 static void amazon_mask_and_ack_irq(unsigned int irq_nr
)
61 /* have to access the correct register here */
62 if (irq_nr
<= INT_NUM_IM0_IRL11
&& irq_nr
>= INT_NUM_IM0_IRL0
) {
63 /* access IM0 DMA channels */
64 *AMAZON_ICU_IM0_IER
&= (~(AMAZON_DMA_H_MASK
)); /* mask */
65 *AMAZON_ICU_IM0_ISR
= AMAZON_DMA_H_MASK
; /* ack */
66 } else if (irq_nr
<= INT_NUM_IM0_IRL31
&& irq_nr
>= INT_NUM_IM0_IRL12
) {
67 /* access IM0 except DMA */
68 *AMAZON_ICU_IM0_IER
&= ~AMAZON_ICU_IM0_IER_IR(irq_nr
- INT_NUM_IM0_IRL0
); /* mask */
69 *AMAZON_ICU_IM0_ISR
= AMAZON_ICU_IM0_ISR_IR(irq_nr
- INT_NUM_IM0_IRL0
); /* ack */
70 } else if (irq_nr
<= INT_NUM_IM1_IRL31
&& irq_nr
>= INT_NUM_IM1_IRL0
) {
72 *AMAZON_ICU_IM1_IER
&= ~AMAZON_ICU_IM1_IER_IR(irq_nr
- INT_NUM_IM1_IRL0
); /* mask */
73 *AMAZON_ICU_IM1_ISR
= AMAZON_ICU_IM1_ISR_IR(irq_nr
- INT_NUM_IM1_IRL0
); /* ack */
74 } else if (irq_nr
<= INT_NUM_IM2_IRL31
&& irq_nr
>= INT_NUM_IM2_IRL0
) {
76 *AMAZON_ICU_IM2_IER
&= ~AMAZON_ICU_IM2_IER_IR(irq_nr
- INT_NUM_IM2_IRL0
); /* mask */
77 *AMAZON_ICU_IM2_ISR
= AMAZON_ICU_IM2_ISR_IR(irq_nr
- INT_NUM_IM2_IRL0
); /* ack */
78 } else if (irq_nr
<= INT_NUM_IM3_IRL31
&& irq_nr
>= INT_NUM_IM3_IRL0
) {
80 *AMAZON_ICU_IM3_IER
&= ~AMAZON_ICU_IM3_IER_IR(irq_nr
- INT_NUM_IM3_IRL0
); /* mask */
81 *AMAZON_ICU_IM3_ISR
= AMAZON_ICU_IM3_ISR_IR(irq_nr
- INT_NUM_IM3_IRL0
); /* ack */
82 } else if (irq_nr
<= INT_NUM_IM4_IRL31
&& irq_nr
>= INT_NUM_IM4_IRL0
) {
83 *AMAZON_ICU_IM4_IER
&= ~AMAZON_ICU_IM4_IER_IR(irq_nr
- INT_NUM_IM4_IRL0
); /* mask */
84 *AMAZON_ICU_IM4_ISR
= AMAZON_ICU_IM4_ISR_IR(irq_nr
- INT_NUM_IM4_IRL0
); /* ack */
88 static void amazon_enable_irq(unsigned int irq_nr
)
90 /* have to access the correct register here */
91 if (irq_nr
<= INT_NUM_IM0_IRL11
&& irq_nr
>= INT_NUM_IM0_IRL0
)
93 *AMAZON_ICU_IM0_IER
|= AMAZON_DMA_H_MASK
;
94 else if (irq_nr
<= INT_NUM_IM0_IRL31
&& irq_nr
>= INT_NUM_IM0_IRL12
)
95 /* access IM0 except DMA*/
96 *AMAZON_ICU_IM0_IER
|= AMAZON_ICU_IM0_IER_IR(irq_nr
- INT_NUM_IM0_IRL0
);
97 else if (irq_nr
<= INT_NUM_IM1_IRL31
&& irq_nr
>= INT_NUM_IM1_IRL0
)
99 *AMAZON_ICU_IM1_IER
|= AMAZON_ICU_IM1_IER_IR(irq_nr
- INT_NUM_IM1_IRL0
);
100 else if (irq_nr
<= INT_NUM_IM2_IRL31
&& irq_nr
>= INT_NUM_IM2_IRL0
)
102 *AMAZON_ICU_IM2_IER
|= AMAZON_ICU_IM2_IER_IR(irq_nr
- INT_NUM_IM2_IRL0
);
103 else if (irq_nr
<= INT_NUM_IM3_IRL31
&& irq_nr
>= INT_NUM_IM3_IRL0
)
105 *AMAZON_ICU_IM3_IER
|= AMAZON_ICU_IM3_IER_IR((irq_nr
- INT_NUM_IM3_IRL0
));
106 else if (irq_nr
<= INT_NUM_IM4_IRL31
&& irq_nr
>= INT_NUM_IM4_IRL0
)
108 *AMAZON_ICU_IM4_IER
|= AMAZON_ICU_IM4_IER_IR((irq_nr
- INT_NUM_IM4_IRL0
));
111 static unsigned int amazon_startup_irq(unsigned int irq
)
113 amazon_enable_irq(irq
);
117 static void amazon_end_irq(unsigned int irq
)
119 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
|IRQ_INPROGRESS
))) {
120 amazon_enable_irq(irq
);
124 static struct hw_interrupt_type amazon_irq_type
= {
126 .startup
= amazon_startup_irq
,
127 .enable
= amazon_enable_irq
,
128 .disable
= amazon_disable_irq
,
129 .unmask
= amazon_enable_irq
,
130 .ack
= amazon_mask_and_ack_irq
,
131 .mask
= amazon_disable_irq
,
132 .mask_ack
= amazon_mask_and_ack_irq
,
133 .end
= amazon_end_irq
136 /* Cascaded interrupts from IM0 */
137 static inline void amazon_hw0_irqdispatch(void)
141 irq
= (*AMAZON_ICU_IM_VEC
) & AMAZON_ICU_IM0_VEC_MASK
;
142 if (irq
<= 11 && irq
>= 0) {
143 //DMA fixed to IM0_IRL0
146 do_IRQ(irq
+ INT_NUM_IM0_IRL0
);
149 /* Cascaded interrupts from IM1 */
150 static inline void amazon_hw1_irqdispatch(void)
154 irq
= ((*AMAZON_ICU_IM_VEC
) & AMAZON_ICU_IM1_VEC_MASK
) >> 5;
155 do_IRQ(irq
+ INT_NUM_IM1_IRL0
);
158 /* Cascaded interrupts from IM2 */
159 static inline void amazon_hw2_irqdispatch(void)
163 irq
= ((*AMAZON_ICU_IM_VEC
) & AMAZON_ICU_IM2_VEC_MASK
) >> 10;
164 do_IRQ(irq
+ INT_NUM_IM2_IRL0
);
167 /* Cascaded interrupts from IM3 */
168 static inline void amazon_hw3_irqdispatch(void)
172 irq
= ((*AMAZON_ICU_IM_VEC
) & AMAZON_ICU_IM3_VEC_MASK
) >> 15;
173 do_IRQ(irq
+ INT_NUM_IM3_IRL0
);
176 /* Cascaded interrupts from IM4 */
177 static inline void amazon_hw4_irqdispatch(void)
181 irq
= ((*AMAZON_ICU_IM_VEC
) & AMAZON_ICU_IM4_VEC_MASK
) >> 20;
182 do_IRQ(irq
+ INT_NUM_IM4_IRL0
);
185 asmlinkage
void plat_irq_dispatch(void)
187 unsigned int pending
= read_c0_status() & read_c0_cause() & ST0_IM
;
188 if (pending
& CAUSEF_IP7
){
189 do_IRQ(MIPS_CPU_TIMER_IRQ
);
191 else if (pending
& CAUSEF_IP2
)
192 amazon_hw0_irqdispatch();
193 else if (pending
& CAUSEF_IP3
)
194 amazon_hw1_irqdispatch();
195 else if (pending
& CAUSEF_IP4
)
196 amazon_hw2_irqdispatch();
197 else if (pending
& CAUSEF_IP5
)
198 amazon_hw3_irqdispatch();
199 else if (pending
& CAUSEF_IP6
)
200 amazon_hw4_irqdispatch();
202 printk("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
205 static struct irqaction cascade
= {
206 .handler
= no_action
,
207 .flags
= SA_INTERRUPT
,
212 /* Function for careful CP0 interrupt mask access */
214 void __init
arch_init_irq(void)
218 /* mask all interrupt sources */
219 *AMAZON_ICU_IM0_IER
= 0;
220 *AMAZON_ICU_IM1_IER
= 0;
221 *AMAZON_ICU_IM2_IER
= 0;
222 *AMAZON_ICU_IM3_IER
= 0;
223 *AMAZON_ICU_IM4_IER
= 0;
227 /* set up irq cascade */
228 for (i
= 2; i
<= 6; i
++) {
229 setup_irq(i
, &cascade
);
232 for (i
= INT_NUM_IRQ0
; i
<= INT_NUM_IM4_IRL31
; i
++) {
233 irq_desc
[i
].status
= IRQ_DISABLED
;
234 irq_desc
[i
].action
= 0;
235 irq_desc
[i
].depth
= 1;
236 set_irq_chip(i
, &amazon_irq_type
);