aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/au1000/common/irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/au1000/common/irq.c')
-rw-r--r--arch/mips/au1000/common/irq.c105
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);
83void (*board_init_irq)(void); 83void (*board_init_irq)(void);
84 84
85#ifdef CONFIG_PM 85#ifdef CONFIG_PM
86extern void counter0_irq(int irq, void *dev_id, struct pt_regs *regs); 86extern irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs);
87#endif 87#endif
88 88
89static DEFINE_SPINLOCK(irq_lock); 89static DEFINE_SPINLOCK(irq_lock);
@@ -253,52 +253,72 @@ void restore_local_and_enable(int controller, unsigned long mask)
253 253
254 254
255static struct hw_interrupt_type rise_edge_irq_type = { 255static 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
266static struct hw_interrupt_type fall_edge_irq_type = { 265static 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
277static struct hw_interrupt_type either_edge_irq_type = { 275static 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
288static struct hw_interrupt_type level_irq_type = { 285static 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
300void startup_match20_interrupt(void) 296void 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