aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v10/kernel/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/cris/arch-v10/kernel/irq.c')
-rw-r--r--arch/cris/arch-v10/kernel/irq.c59
1 files changed, 57 insertions, 2 deletions
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c
index 845c95f6e871..e06ab0050d37 100644
--- a/arch/cris/arch-v10/kernel/irq.c
+++ b/arch/cris/arch-v10/kernel/irq.c
@@ -12,10 +12,16 @@
12 */ 12 */
13 13
14#include <asm/irq.h> 14#include <asm/irq.h>
15#include <asm/current.h>
15#include <linux/irq.h> 16#include <linux/irq.h>
17#include <linux/interrupt.h>
16#include <linux/kernel.h> 18#include <linux/kernel.h>
17#include <linux/init.h> 19#include <linux/init.h>
18 20
21/* From kgdb.c. */
22extern void kgdb_init(void);
23extern void breakpoint(void);
24
19#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); 25#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
20#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); 26#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
21 27
@@ -75,8 +81,8 @@ BUILD_IRQ(12, 0x1000)
75BUILD_IRQ(13, 0x2000) 81BUILD_IRQ(13, 0x2000)
76void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */ 82void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */
77void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */ 83void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
78BUILD_IRQ(16, 0x10000) 84BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */
79BUILD_IRQ(17, 0x20000) 85BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */
80BUILD_IRQ(18, 0x40000) 86BUILD_IRQ(18, 0x40000)
81BUILD_IRQ(19, 0x80000) 87BUILD_IRQ(19, 0x80000)
82BUILD_IRQ(20, 0x100000) 88BUILD_IRQ(20, 0x100000)
@@ -147,6 +153,55 @@ void system_call(void); /* from entry.S */
147void do_sigtrap(void); /* from entry.S */ 153void do_sigtrap(void); /* from entry.S */
148void gdb_handle_breakpoint(void); /* from entry.S */ 154void gdb_handle_breakpoint(void); /* from entry.S */
149 155
156extern void do_IRQ(int irq, struct pt_regs * regs);
157
158/* Handle multiple IRQs */
159void do_multiple_IRQ(struct pt_regs* regs)
160{
161 int bit;
162 unsigned masked;
163 unsigned mask;
164 unsigned ethmask = 0;
165
166 /* Get interrupts to mask and handle */
167 mask = masked = *R_VECT_MASK_RD;
168
169 /* Never mask timer IRQ */
170 mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0));
171
172 /*
173 * If either ethernet interrupt (rx or tx) is active then block
174 * the other one too. Unblock afterwards also.
175 */
176 if (mask &
177 (IO_STATE(R_VECT_MASK_RD, dma0, active) |
178 IO_STATE(R_VECT_MASK_RD, dma1, active))) {
179 ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) |
180 IO_MASK(R_VECT_MASK_RD, dma1));
181 }
182
183 /* Block them */
184 *R_VECT_MASK_CLR = (mask | ethmask);
185
186 /* An extra irq_enter here to prevent softIRQs to run after
187 * each do_IRQ. This will decrease the interrupt latency.
188 */
189 irq_enter();
190
191 /* Handle all IRQs */
192 for (bit = 2; bit < 32; bit++) {
193 if (masked & (1 << bit)) {
194 do_IRQ(bit, regs);
195 }
196 }
197
198 /* This irq_exit() will trigger the soft IRQs. */
199 irq_exit();
200
201 /* Unblock the IRQs again */
202 *R_VECT_MASK_SET = (masked | ethmask);
203}
204
150/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and 205/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
151 setting the irq vector table. 206 setting the irq vector table.
152*/ 207*/