diff options
Diffstat (limited to 'include/asm-cris/arch-v32/irq.h')
-rw-r--r-- | include/asm-cris/arch-v32/irq.h | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/include/asm-cris/arch-v32/irq.h b/include/asm-cris/arch-v32/irq.h new file mode 100644 index 000000000000..d35aa8174c2f --- /dev/null +++ b/include/asm-cris/arch-v32/irq.h | |||
@@ -0,0 +1,120 @@ | |||
1 | #ifndef _ASM_ARCH_IRQ_H | ||
2 | #define _ASM_ARCH_IRQ_H | ||
3 | |||
4 | #include <linux/config.h> | ||
5 | #include "hwregs/intr_vect.h" | ||
6 | |||
7 | /* Number of non-cpu interrupts. */ | ||
8 | #define NR_IRQS 0x50 /* Exceptions + IRQs */ | ||
9 | #define NR_REAL_IRQS 0x20 /* IRQs */ | ||
10 | #define FIRST_IRQ 0x31 /* Exception number for first IRQ */ | ||
11 | |||
12 | #ifndef __ASSEMBLY__ | ||
13 | /* Global IRQ vector. */ | ||
14 | typedef void (*irqvectptr)(void); | ||
15 | |||
16 | struct etrax_interrupt_vector { | ||
17 | irqvectptr v[256]; | ||
18 | }; | ||
19 | |||
20 | extern struct etrax_interrupt_vector *etrax_irv; /* head.S */ | ||
21 | |||
22 | void mask_irq(int irq); | ||
23 | void unmask_irq(int irq); | ||
24 | |||
25 | void set_exception_vector(int n, irqvectptr addr); | ||
26 | |||
27 | /* Save registers so that they match pt_regs. */ | ||
28 | #define SAVE_ALL \ | ||
29 | "subq 12,$sp\n\t" \ | ||
30 | "move $erp,[$sp]\n\t" \ | ||
31 | "subq 4,$sp\n\t" \ | ||
32 | "move $srp,[$sp]\n\t" \ | ||
33 | "subq 4,$sp\n\t" \ | ||
34 | "move $ccs,[$sp]\n\t" \ | ||
35 | "subq 4,$sp\n\t" \ | ||
36 | "move $spc,[$sp]\n\t" \ | ||
37 | "subq 4,$sp\n\t" \ | ||
38 | "move $mof,[$sp]\n\t" \ | ||
39 | "subq 4,$sp\n\t" \ | ||
40 | "move $srs,[$sp]\n\t" \ | ||
41 | "subq 4,$sp\n\t" \ | ||
42 | "move.d $acr,[$sp]\n\t" \ | ||
43 | "subq 14*4,$sp\n\t" \ | ||
44 | "movem $r13,[$sp]\n\t" \ | ||
45 | "subq 4,$sp\n\t" \ | ||
46 | "move.d $r10,[$sp]\n" | ||
47 | |||
48 | #define STR2(x) #x | ||
49 | #define STR(x) STR2(x) | ||
50 | |||
51 | #define IRQ_NAME2(nr) nr##_interrupt(void) | ||
52 | #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) | ||
53 | |||
54 | /* | ||
55 | * The reason for setting the S-bit when debugging the kernel is that we want | ||
56 | * hardware breakpoints to remain active while we are in an exception handler. | ||
57 | * Note that we cannot simply copy S1, since we may come here from user-space, | ||
58 | * or any context where the S-bit wasn't set. | ||
59 | */ | ||
60 | #ifdef CONFIG_ETRAX_KGDB | ||
61 | #define KGDB_FIXUP \ | ||
62 | "move $ccs, $r10\n\t" \ | ||
63 | "or.d (1<<9), $r10\n\t" \ | ||
64 | "move $r10, $ccs\n\t" | ||
65 | #else | ||
66 | #define KGDB_FIXUP "" | ||
67 | #endif | ||
68 | |||
69 | /* | ||
70 | * Make sure the causing IRQ is blocked, then call do_IRQ. After that, unblock | ||
71 | * and jump to ret_from_intr which is found in entry.S. | ||
72 | * | ||
73 | * The reason for blocking the IRQ is to allow an sti() before the handler, | ||
74 | * which will acknowledge the interrupt, is run. The actual blocking is made | ||
75 | * by crisv32_do_IRQ. | ||
76 | */ | ||
77 | #define BUILD_IRQ(nr, mask) \ | ||
78 | void IRQ_NAME(nr); \ | ||
79 | __asm__ ( \ | ||
80 | ".text\n\t" \ | ||
81 | "IRQ" #nr "_interrupt:\n\t" \ | ||
82 | SAVE_ALL \ | ||
83 | KGDB_FIXUP \ | ||
84 | "move.d "#nr",$r10\n\t" \ | ||
85 | "move.d $sp,$r12\n\t" \ | ||
86 | "jsr crisv32_do_IRQ\n\t" \ | ||
87 | "moveq 1, $r11\n\t" \ | ||
88 | "jump ret_from_intr\n\t" \ | ||
89 | "nop\n\t"); | ||
90 | /* | ||
91 | * This is subtle. The timer interrupt is crucial and it should not be disabled | ||
92 | * for too long. However, if it had been a normal interrupt as per BUILD_IRQ, it | ||
93 | * would have been BLOCK'ed, and then softirq's are run before we return here to | ||
94 | * UNBLOCK. If the softirq's take too much time to run, the timer irq won't run | ||
95 | * and the watchdog will kill us. | ||
96 | * | ||
97 | * Furthermore, if a lot of other irq's occur before we return here, the | ||
98 | * multiple_irq handler is run and it prioritizes the timer interrupt. However | ||
99 | * if we had BLOCK'edit here, we would not get the multiple_irq at all. | ||
100 | * | ||
101 | * The non-blocking here is based on the knowledge that the timer interrupt is | ||
102 | * registred as a fast interrupt (SA_INTERRUPT) so that we _know_ there will not | ||
103 | * be an sti() before the timer irq handler is run to acknowledge the interrupt. | ||
104 | */ | ||
105 | #define BUILD_TIMER_IRQ(nr, mask) \ | ||
106 | void IRQ_NAME(nr); \ | ||
107 | __asm__ ( \ | ||
108 | ".text\n\t" \ | ||
109 | "IRQ" #nr "_interrupt:\n\t" \ | ||
110 | SAVE_ALL \ | ||
111 | KGDB_FIXUP \ | ||
112 | "move.d "#nr",$r10\n\t" \ | ||
113 | "move.d $sp,$r12\n\t" \ | ||
114 | "jsr crisv32_do_IRQ\n\t" \ | ||
115 | "moveq 0,$r11\n\t" \ | ||
116 | "jump ret_from_intr\n\t" \ | ||
117 | "nop\n\t"); | ||
118 | |||
119 | #endif /* __ASSEMBLY__ */ | ||
120 | #endif /* _ASM_ARCH_IRQ_H */ | ||