diff options
-rw-r--r-- | arch/arm/mach-pxa/viper.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index d7632f63603c..4b3120dbc049 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c | |||
@@ -204,25 +204,54 @@ static void viper_set_core_cpu_voltage(unsigned long khz, int force) | |||
204 | 204 | ||
205 | /* Interrupt handling */ | 205 | /* Interrupt handling */ |
206 | static unsigned long viper_irq_enabled_mask; | 206 | static unsigned long viper_irq_enabled_mask; |
207 | static const int viper_isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, 9, 14, 15 }; | ||
208 | static const int viper_isa_irq_map[] = { | ||
209 | 0, /* ISA irq #0, invalid */ | ||
210 | 0, /* ISA irq #1, invalid */ | ||
211 | 0, /* ISA irq #2, invalid */ | ||
212 | 1 << 0, /* ISA irq #3 */ | ||
213 | 1 << 1, /* ISA irq #4 */ | ||
214 | 1 << 2, /* ISA irq #5 */ | ||
215 | 1 << 3, /* ISA irq #6 */ | ||
216 | 1 << 4, /* ISA irq #7 */ | ||
217 | 0, /* ISA irq #8, invalid */ | ||
218 | 1 << 8, /* ISA irq #9 */ | ||
219 | 1 << 5, /* ISA irq #10 */ | ||
220 | 1 << 6, /* ISA irq #11 */ | ||
221 | 1 << 7, /* ISA irq #12 */ | ||
222 | 0, /* ISA irq #13, invalid */ | ||
223 | 1 << 9, /* ISA irq #14 */ | ||
224 | 1 << 10, /* ISA irq #15 */ | ||
225 | }; | ||
226 | |||
227 | static inline int viper_irq_to_bitmask(unsigned int irq) | ||
228 | { | ||
229 | return viper_isa_irq_map[irq - PXA_ISA_IRQ(0)]; | ||
230 | } | ||
231 | |||
232 | static inline int viper_bit_to_irq(int bit) | ||
233 | { | ||
234 | return viper_isa_irqs[bit] + PXA_ISA_IRQ(0); | ||
235 | } | ||
207 | 236 | ||
208 | static void viper_ack_irq(unsigned int irq) | 237 | static void viper_ack_irq(unsigned int irq) |
209 | { | 238 | { |
210 | int viper_irq = irq - PXA_ISA_IRQ(0); | 239 | int viper_irq = viper_irq_to_bitmask(irq); |
211 | 240 | ||
212 | if (viper_irq < 8) | 241 | if (viper_irq & 0xff) |
213 | VIPER_LO_IRQ_STATUS = 1 << viper_irq; | 242 | VIPER_LO_IRQ_STATUS = viper_irq; |
214 | else | 243 | else |
215 | VIPER_HI_IRQ_STATUS = 1 << (viper_irq - 8); | 244 | VIPER_HI_IRQ_STATUS = (viper_irq >> 8); |
216 | } | 245 | } |
217 | 246 | ||
218 | static void viper_mask_irq(unsigned int irq) | 247 | static void viper_mask_irq(unsigned int irq) |
219 | { | 248 | { |
220 | viper_irq_enabled_mask &= ~(1 << (irq - PXA_ISA_IRQ(0))); | 249 | viper_irq_enabled_mask &= ~(viper_irq_to_bitmask(irq)); |
221 | } | 250 | } |
222 | 251 | ||
223 | static void viper_unmask_irq(unsigned int irq) | 252 | static void viper_unmask_irq(unsigned int irq) |
224 | { | 253 | { |
225 | viper_irq_enabled_mask |= (1 << (irq - PXA_ISA_IRQ(0))); | 254 | viper_irq_enabled_mask |= viper_irq_to_bitmask(irq); |
226 | } | 255 | } |
227 | 256 | ||
228 | static inline unsigned long viper_irq_pending(void) | 257 | static inline unsigned long viper_irq_pending(void) |
@@ -237,8 +266,12 @@ static void viper_irq_handler(unsigned int irq, struct irq_desc *desc) | |||
237 | 266 | ||
238 | pending = viper_irq_pending(); | 267 | pending = viper_irq_pending(); |
239 | do { | 268 | do { |
269 | /* we're in a chained irq handler, | ||
270 | * so ack the interrupt by hand */ | ||
271 | GEDR(VIPER_CPLD_GPIO) = GPIO_bit(VIPER_CPLD_GPIO); | ||
272 | |||
240 | if (likely(pending)) { | 273 | if (likely(pending)) { |
241 | irq = PXA_ISA_IRQ(0) + __ffs(pending); | 274 | irq = viper_bit_to_irq(__ffs(pending)); |
242 | generic_handle_irq(irq); | 275 | generic_handle_irq(irq); |
243 | } | 276 | } |
244 | pending = viper_irq_pending(); | 277 | pending = viper_irq_pending(); |
@@ -254,15 +287,14 @@ static struct irq_chip viper_irq_chip = { | |||
254 | 287 | ||
255 | static void __init viper_init_irq(void) | 288 | static void __init viper_init_irq(void) |
256 | { | 289 | { |
257 | const int isa_irqs[] = { 3, 4, 5, 6, 7, 10, 11, 12, 9, 14, 15 }; | 290 | int level; |
258 | int irq; | ||
259 | int isa_irq; | 291 | int isa_irq; |
260 | 292 | ||
261 | pxa25x_init_irq(); | 293 | pxa25x_init_irq(); |
262 | 294 | ||
263 | /* setup ISA IRQs */ | 295 | /* setup ISA IRQs */ |
264 | for (irq = 0; irq < ARRAY_SIZE(isa_irqs); irq++) { | 296 | for (level = 0; level < ARRAY_SIZE(viper_isa_irqs); level++) { |
265 | isa_irq = isa_irqs[irq]; | 297 | isa_irq = viper_bit_to_irq(level); |
266 | set_irq_chip(isa_irq, &viper_irq_chip); | 298 | set_irq_chip(isa_irq, &viper_irq_chip); |
267 | set_irq_handler(isa_irq, handle_edge_irq); | 299 | set_irq_handler(isa_irq, handle_edge_irq); |
268 | set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE); | 300 | set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE); |