diff options
Diffstat (limited to 'arch/cris/arch-v10/kernel/irq.c')
-rw-r--r-- | arch/cris/arch-v10/kernel/irq.c | 76 |
1 files changed, 43 insertions, 33 deletions
diff --git a/arch/cris/arch-v10/kernel/irq.c b/arch/cris/arch-v10/kernel/irq.c index b2f16d6fc871..4b368a122015 100644 --- a/arch/cris/arch-v10/kernel/irq.c +++ b/arch/cris/arch-v10/kernel/irq.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $Id: irq.c,v 1.2 2004/06/09 05:30:27 starvik Exp $ | 1 | /* $Id: irq.c,v 1.4 2005/01/04 12:22:28 starvik Exp $ |
2 | * | 2 | * |
3 | * linux/arch/cris/kernel/irq.c | 3 | * linux/arch/cris/kernel/irq.c |
4 | * | 4 | * |
@@ -12,11 +12,13 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
15 | #include <linux/irq.h> | ||
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/init.h> | 17 | #include <linux/init.h> |
17 | #include <linux/config.h> | 18 | #include <linux/config.h> |
18 | 19 | ||
19 | irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */ | 20 | #define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); |
21 | #define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); | ||
20 | 22 | ||
21 | /* don't use set_int_vector, it bypasses the linux interrupt handlers. it is | 23 | /* don't use set_int_vector, it bypasses the linux interrupt handlers. it is |
22 | * global just so that the kernel gdb can use it. | 24 | * global just so that the kernel gdb can use it. |
@@ -102,41 +104,52 @@ static void (*interrupt[NR_IRQS])(void) = { | |||
102 | IRQ31_interrupt | 104 | IRQ31_interrupt |
103 | }; | 105 | }; |
104 | 106 | ||
105 | static void (*bad_interrupt[NR_IRQS])(void) = { | 107 | static void enable_crisv10_irq(unsigned int irq); |
106 | NULL, NULL, | 108 | |
107 | NULL, bad_IRQ3_interrupt, | 109 | static unsigned int startup_crisv10_irq(unsigned int irq) |
108 | bad_IRQ4_interrupt, bad_IRQ5_interrupt, | 110 | { |
109 | bad_IRQ6_interrupt, bad_IRQ7_interrupt, | 111 | enable_crisv10_irq(irq); |
110 | bad_IRQ8_interrupt, bad_IRQ9_interrupt, | 112 | return 0; |
111 | bad_IRQ10_interrupt, bad_IRQ11_interrupt, | 113 | } |
112 | bad_IRQ12_interrupt, bad_IRQ13_interrupt, | 114 | |
113 | NULL, NULL, | 115 | #define shutdown_crisv10_irq disable_crisv10_irq |
114 | bad_IRQ16_interrupt, bad_IRQ17_interrupt, | ||
115 | bad_IRQ18_interrupt, bad_IRQ19_interrupt, | ||
116 | bad_IRQ20_interrupt, bad_IRQ21_interrupt, | ||
117 | bad_IRQ22_interrupt, bad_IRQ23_interrupt, | ||
118 | bad_IRQ24_interrupt, bad_IRQ25_interrupt, | ||
119 | NULL, NULL, NULL, NULL, NULL, | ||
120 | bad_IRQ31_interrupt | ||
121 | }; | ||
122 | 116 | ||
123 | void arch_setup_irq(int irq) | 117 | static void enable_crisv10_irq(unsigned int irq) |
124 | { | 118 | { |
125 | set_int_vector(irq, interrupt[irq]); | 119 | unmask_irq(irq); |
126 | } | 120 | } |
127 | 121 | ||
128 | void arch_free_irq(int irq) | 122 | static void disable_crisv10_irq(unsigned int irq) |
129 | { | 123 | { |
130 | set_int_vector(irq, bad_interrupt[irq]); | 124 | mask_irq(irq); |
131 | } | 125 | } |
132 | 126 | ||
127 | static void ack_crisv10_irq(unsigned int irq) | ||
128 | { | ||
129 | } | ||
130 | |||
131 | static void end_crisv10_irq(unsigned int irq) | ||
132 | { | ||
133 | } | ||
134 | |||
135 | static struct hw_interrupt_type crisv10_irq_type = { | ||
136 | .typename = "CRISv10", | ||
137 | .startup = startup_crisv10_irq, | ||
138 | .shutdown = shutdown_crisv10_irq, | ||
139 | .enable = enable_crisv10_irq, | ||
140 | .disable = disable_crisv10_irq, | ||
141 | .ack = ack_crisv10_irq, | ||
142 | .end = end_crisv10_irq, | ||
143 | .set_affinity = NULL | ||
144 | }; | ||
145 | |||
133 | void weird_irq(void); | 146 | void weird_irq(void); |
134 | void system_call(void); /* from entry.S */ | 147 | void system_call(void); /* from entry.S */ |
135 | void do_sigtrap(void); /* from entry.S */ | 148 | void do_sigtrap(void); /* from entry.S */ |
136 | void gdb_handle_breakpoint(void); /* from entry.S */ | 149 | void gdb_handle_breakpoint(void); /* from entry.S */ |
137 | 150 | ||
138 | /* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and | 151 | /* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and |
139 | setting the irq vector table to point to bad_interrupt ptrs. | 152 | setting the irq vector table. |
140 | */ | 153 | */ |
141 | 154 | ||
142 | void __init | 155 | void __init |
@@ -154,14 +167,15 @@ init_IRQ(void) | |||
154 | 167 | ||
155 | *R_VECT_MASK_CLR = 0xffffffff; | 168 | *R_VECT_MASK_CLR = 0xffffffff; |
156 | 169 | ||
157 | /* clear the shortcut entry points */ | ||
158 | |||
159 | for(i = 0; i < NR_IRQS; i++) | ||
160 | irq_shortcuts[i] = NULL; | ||
161 | |||
162 | for (i = 0; i < 256; i++) | 170 | for (i = 0; i < 256; i++) |
163 | etrax_irv->v[i] = weird_irq; | 171 | etrax_irv->v[i] = weird_irq; |
164 | 172 | ||
173 | /* Initialize IRQ handler descriptiors. */ | ||
174 | for(i = 2; i < NR_IRQS; i++) { | ||
175 | irq_desc[i].handler = &crisv10_irq_type; | ||
176 | set_int_vector(i, interrupt[i]); | ||
177 | } | ||
178 | |||
165 | /* the entries in the break vector contain actual code to be | 179 | /* the entries in the break vector contain actual code to be |
166 | executed by the associated break handler, rather than just a jump | 180 | executed by the associated break handler, rather than just a jump |
167 | address. therefore we need to setup a default breakpoint handler | 181 | address. therefore we need to setup a default breakpoint handler |
@@ -170,10 +184,6 @@ init_IRQ(void) | |||
170 | for (i = 0; i < 16; i++) | 184 | for (i = 0; i < 16; i++) |
171 | set_break_vector(i, do_sigtrap); | 185 | set_break_vector(i, do_sigtrap); |
172 | 186 | ||
173 | /* set all etrax irq's to the bad handlers */ | ||
174 | for (i = 2; i < NR_IRQS; i++) | ||
175 | set_int_vector(i, bad_interrupt[i]); | ||
176 | |||
177 | /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */ | 187 | /* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */ |
178 | 188 | ||
179 | set_int_vector(15, multiple_interrupt); | 189 | set_int_vector(15, multiple_interrupt); |