diff options
Diffstat (limited to 'arch/mips/au1000/common/irq.c')
-rw-r--r-- | arch/mips/au1000/common/irq.c | 105 |
1 files changed, 57 insertions, 48 deletions
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index d1eb5a4a9a19..1339a0979f66 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c | |||
@@ -83,7 +83,7 @@ inline void local_disable_irq(unsigned int irq_nr); | |||
83 | void (*board_init_irq)(void); | 83 | void (*board_init_irq)(void); |
84 | 84 | ||
85 | #ifdef CONFIG_PM | 85 | #ifdef CONFIG_PM |
86 | extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs); | 86 | extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs); |
87 | #endif | 87 | #endif |
88 | 88 | ||
89 | static DEFINE_SPINLOCK(irq_lock); | 89 | static DEFINE_SPINLOCK(irq_lock); |
@@ -253,52 +253,72 @@ void restore_local_and_enable(int controller, unsigned long mask) | |||
253 | 253 | ||
254 | 254 | ||
255 | static struct hw_interrupt_type rise_edge_irq_type = { | 255 | static struct hw_interrupt_type rise_edge_irq_type = { |
256 | "Au1000 Rise Edge", | 256 | .typename = "Au1000 Rise Edge", |
257 | startup_irq, | 257 | .startup = startup_irq, |
258 | shutdown_irq, | 258 | .shutdown = shutdown_irq, |
259 | local_enable_irq, | 259 | .enable = local_enable_irq, |
260 | local_disable_irq, | 260 | .disable = local_disable_irq, |
261 | mask_and_ack_rise_edge_irq, | 261 | .ack = mask_and_ack_rise_edge_irq, |
262 | end_irq, | 262 | .end = end_irq, |
263 | NULL | ||
264 | }; | 263 | }; |
265 | 264 | ||
266 | static struct hw_interrupt_type fall_edge_irq_type = { | 265 | static struct hw_interrupt_type fall_edge_irq_type = { |
267 | "Au1000 Fall Edge", | 266 | .typename = "Au1000 Fall Edge", |
268 | startup_irq, | 267 | .startup = startup_irq, |
269 | shutdown_irq, | 268 | .shutdown = shutdown_irq, |
270 | local_enable_irq, | 269 | .enable = local_enable_irq, |
271 | local_disable_irq, | 270 | .disable = local_disable_irq, |
272 | mask_and_ack_fall_edge_irq, | 271 | .ack = mask_and_ack_fall_edge_irq, |
273 | end_irq, | 272 | .end = end_irq, |
274 | NULL | ||
275 | }; | 273 | }; |
276 | 274 | ||
277 | static struct hw_interrupt_type either_edge_irq_type = { | 275 | static struct hw_interrupt_type either_edge_irq_type = { |
278 | "Au1000 Rise or Fall Edge", | 276 | .typename = "Au1000 Rise or Fall Edge", |
279 | startup_irq, | 277 | .startup = startup_irq, |
280 | shutdown_irq, | 278 | .shutdown = shutdown_irq, |
281 | local_enable_irq, | 279 | .enable = local_enable_irq, |
282 | local_disable_irq, | 280 | .disable = local_disable_irq, |
283 | mask_and_ack_either_edge_irq, | 281 | .ack = mask_and_ack_either_edge_irq, |
284 | end_irq, | 282 | .end = end_irq, |
285 | NULL | ||
286 | }; | 283 | }; |
287 | 284 | ||
288 | static struct hw_interrupt_type level_irq_type = { | 285 | static struct hw_interrupt_type level_irq_type = { |
289 | "Au1000 Level", | 286 | .typename = "Au1000 Level", |
290 | startup_irq, | 287 | .startup = startup_irq, |
291 | shutdown_irq, | 288 | .shutdown = shutdown_irq, |
292 | local_enable_irq, | 289 | .enable = local_enable_irq, |
293 | local_disable_irq, | 290 | .disable = local_disable_irq, |
294 | mask_and_ack_level_irq, | 291 | .ack = mask_and_ack_level_irq, |
295 | end_irq, | 292 | .end = end_irq, |
296 | NULL | ||
297 | }; | 293 | }; |
298 | 294 | ||
299 | #ifdef CONFIG_PM | 295 | #ifdef CONFIG_PM |
300 | void startup_match20_interrupt(void) | 296 | void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *)) |
301 | { | 297 | { |
298 | struct irq_desc *desc = &irq_desc[AU1000_TOY_MATCH2_INT]; | ||
299 | |||
300 | static struct irqaction action; | ||
301 | memset(&action, 0, sizeof(struct irqaction)); | ||
302 | |||
303 | /* This is a big problem.... since we didn't use request_irq | ||
304 | * when kernel/irq.c calls probe_irq_xxx this interrupt will | ||
305 | * be probed for usage. This will end up disabling the device :( | ||
306 | * Give it a bogus "action" pointer -- this will keep it from | ||
307 | * getting auto-probed! | ||
308 | * | ||
309 | * By setting the status to match that of request_irq() we | ||
310 | * can avoid it. --cgray | ||
311 | */ | ||
312 | action.dev_id = handler; | ||
313 | action.flags = SA_INTERRUPT; | ||
314 | cpus_clear(action.mask); | ||
315 | action.name = "Au1xxx TOY"; | ||
316 | action.handler = handler; | ||
317 | action.next = NULL; | ||
318 | |||
319 | desc->action = &action; | ||
320 | desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); | ||
321 | |||
302 | local_enable_irq(AU1000_TOY_MATCH2_INT); | 322 | local_enable_irq(AU1000_TOY_MATCH2_INT); |
303 | } | 323 | } |
304 | #endif | 324 | #endif |
@@ -426,7 +446,6 @@ void __init arch_init_irq(void) | |||
426 | extern int au1xxx_ic0_nr_irqs; | 446 | extern int au1xxx_ic0_nr_irqs; |
427 | 447 | ||
428 | cp0_status = read_c0_status(); | 448 | cp0_status = read_c0_status(); |
429 | memset(irq_desc, 0, sizeof(irq_desc)); | ||
430 | set_except_vector(0, au1000_IRQ); | 449 | set_except_vector(0, au1000_IRQ); |
431 | 450 | ||
432 | /* Initialize interrupt controllers to a safe state. | 451 | /* Initialize interrupt controllers to a safe state. |
@@ -492,7 +511,7 @@ void intc0_req0_irqdispatch(struct pt_regs *regs) | |||
492 | intc0_req0 |= au_readl(IC0_REQ0INT); | 511 | intc0_req0 |= au_readl(IC0_REQ0INT); |
493 | 512 | ||
494 | if (!intc0_req0) return; | 513 | if (!intc0_req0) return; |
495 | 514 | #ifdef AU1000_USB_DEV_REQ_INT | |
496 | /* | 515 | /* |
497 | * Because of the tight timing of SETUP token to reply | 516 | * Because of the tight timing of SETUP token to reply |
498 | * transactions, the USB devices-side packet complete | 517 | * transactions, the USB devices-side packet complete |
@@ -503,7 +522,7 @@ void intc0_req0_irqdispatch(struct pt_regs *regs) | |||
503 | do_IRQ(AU1000_USB_DEV_REQ_INT, regs); | 522 | do_IRQ(AU1000_USB_DEV_REQ_INT, regs); |
504 | return; | 523 | return; |
505 | } | 524 | } |
506 | 525 | #endif | |
507 | irq = au_ffs(intc0_req0) - 1; | 526 | irq = au_ffs(intc0_req0) - 1; |
508 | intc0_req0 &= ~(1<<irq); | 527 | intc0_req0 &= ~(1<<irq); |
509 | do_IRQ(irq, regs); | 528 | do_IRQ(irq, regs); |
@@ -521,17 +540,7 @@ void intc0_req1_irqdispatch(struct pt_regs *regs) | |||
521 | 540 | ||
522 | irq = au_ffs(intc0_req1) - 1; | 541 | irq = au_ffs(intc0_req1) - 1; |
523 | intc0_req1 &= ~(1<<irq); | 542 | intc0_req1 &= ~(1<<irq); |
524 | #ifdef CONFIG_PM | 543 | do_IRQ(irq, regs); |
525 | if (irq == AU1000_TOY_MATCH2_INT) { | ||
526 | mask_and_ack_rise_edge_irq(irq); | ||
527 | counter0_irq(irq, NULL, regs); | ||
528 | local_enable_irq(irq); | ||
529 | } | ||
530 | else | ||
531 | #endif | ||
532 | { | ||
533 | do_IRQ(irq, regs); | ||
534 | } | ||
535 | } | 544 | } |
536 | 545 | ||
537 | 546 | ||