diff options
Diffstat (limited to 'arch/mips/sgi-ip32/ip32-irq.c')
-rw-r--r-- | arch/mips/sgi-ip32/ip32-irq.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/arch/mips/sgi-ip32/ip32-irq.c b/arch/mips/sgi-ip32/ip32-irq.c index 2eb22d692ed9..8ba08047d164 100644 --- a/arch/mips/sgi-ip32/ip32-irq.c +++ b/arch/mips/sgi-ip32/ip32-irq.c | |||
@@ -31,12 +31,12 @@ | |||
31 | /* issue a PIO read to make sure no PIO writes are pending */ | 31 | /* issue a PIO read to make sure no PIO writes are pending */ |
32 | static void inline flush_crime_bus(void) | 32 | static void inline flush_crime_bus(void) |
33 | { | 33 | { |
34 | volatile unsigned long junk = crime->control; | 34 | crime->control; |
35 | } | 35 | } |
36 | 36 | ||
37 | static void inline flush_mace_bus(void) | 37 | static void inline flush_mace_bus(void) |
38 | { | 38 | { |
39 | volatile unsigned long junk = mace->perif.ctrl.misc; | 39 | mace->perif.ctrl.misc; |
40 | } | 40 | } |
41 | 41 | ||
42 | #undef DEBUG_IRQ | 42 | #undef DEBUG_IRQ |
@@ -130,8 +130,6 @@ struct irqaction memerr_irq = { crime_memerr_intr, SA_INTERRUPT, | |||
130 | struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT, | 130 | struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT, |
131 | CPU_MASK_NONE, "CRIME CPU error", NULL, NULL }; | 131 | CPU_MASK_NONE, "CRIME CPU error", NULL, NULL }; |
132 | 132 | ||
133 | extern void ip32_handle_int(void); | ||
134 | |||
135 | /* | 133 | /* |
136 | * For interrupts wired from a single device to the CPU. Only the clock | 134 | * For interrupts wired from a single device to the CPU. Only the clock |
137 | * uses this it seems, which is IRQ 0 and IP7. | 135 | * uses this it seems, which is IRQ 0 and IP7. |
@@ -503,48 +501,67 @@ static void ip32_unknown_interrupt(struct pt_regs *regs) | |||
503 | 501 | ||
504 | /* CRIME 1.1 appears to deliver all interrupts to this one pin. */ | 502 | /* CRIME 1.1 appears to deliver all interrupts to this one pin. */ |
505 | /* change this to loop over all edge-triggered irqs, exception masked out ones */ | 503 | /* change this to loop over all edge-triggered irqs, exception masked out ones */ |
506 | void ip32_irq0(struct pt_regs *regs) | 504 | static void ip32_irq0(struct pt_regs *regs) |
507 | { | 505 | { |
508 | uint64_t crime_int; | 506 | uint64_t crime_int; |
509 | int irq = 0; | 507 | int irq = 0; |
510 | 508 | ||
511 | crime_int = crime->istat & crime_mask; | 509 | crime_int = crime->istat & crime_mask; |
512 | irq = ffs(crime_int); | 510 | irq = __ffs(crime_int); |
513 | crime_int = 1 << (irq - 1); | 511 | crime_int = 1 << irq; |
514 | 512 | ||
515 | if (crime_int & CRIME_MACEISA_INT_MASK) { | 513 | if (crime_int & CRIME_MACEISA_INT_MASK) { |
516 | unsigned long mace_int = mace->perif.ctrl.istat; | 514 | unsigned long mace_int = mace->perif.ctrl.istat; |
517 | irq = ffs(mace_int & maceisa_mask) + 32; | 515 | irq = __ffs(mace_int & maceisa_mask) + 32; |
518 | } | 516 | } |
517 | irq++; | ||
519 | DBG("*irq %u*\n", irq); | 518 | DBG("*irq %u*\n", irq); |
520 | do_IRQ(irq, regs); | 519 | do_IRQ(irq, regs); |
521 | } | 520 | } |
522 | 521 | ||
523 | void ip32_irq1(struct pt_regs *regs) | 522 | static void ip32_irq1(struct pt_regs *regs) |
524 | { | 523 | { |
525 | ip32_unknown_interrupt(regs); | 524 | ip32_unknown_interrupt(regs); |
526 | } | 525 | } |
527 | 526 | ||
528 | void ip32_irq2(struct pt_regs *regs) | 527 | static void ip32_irq2(struct pt_regs *regs) |
529 | { | 528 | { |
530 | ip32_unknown_interrupt(regs); | 529 | ip32_unknown_interrupt(regs); |
531 | } | 530 | } |
532 | 531 | ||
533 | void ip32_irq3(struct pt_regs *regs) | 532 | static void ip32_irq3(struct pt_regs *regs) |
534 | { | 533 | { |
535 | ip32_unknown_interrupt(regs); | 534 | ip32_unknown_interrupt(regs); |
536 | } | 535 | } |
537 | 536 | ||
538 | void ip32_irq4(struct pt_regs *regs) | 537 | static void ip32_irq4(struct pt_regs *regs) |
539 | { | 538 | { |
540 | ip32_unknown_interrupt(regs); | 539 | ip32_unknown_interrupt(regs); |
541 | } | 540 | } |
542 | 541 | ||
543 | void ip32_irq5(struct pt_regs *regs) | 542 | static void ip32_irq5(struct pt_regs *regs) |
544 | { | 543 | { |
545 | ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs); | 544 | ll_timer_interrupt(IP32_R4K_TIMER_IRQ, regs); |
546 | } | 545 | } |
547 | 546 | ||
547 | asmlinkage void plat_irq_dispatch(struct pt_regs *regs) | ||
548 | { | ||
549 | unsigned int pending = read_c0_cause(); | ||
550 | |||
551 | if (likely(pending & IE_IRQ0)) | ||
552 | ip32_irq0(regs); | ||
553 | else if (unlikely(pending & IE_IRQ1)) | ||
554 | ip32_irq1(regs); | ||
555 | else if (unlikely(pending & IE_IRQ2)) | ||
556 | ip32_irq2(regs); | ||
557 | else if (unlikely(pending & IE_IRQ3)) | ||
558 | ip32_irq3(regs); | ||
559 | else if (unlikely(pending & IE_IRQ4)) | ||
560 | ip32_irq4(regs); | ||
561 | else if (likely(pending & IE_IRQ5)) | ||
562 | ip32_irq5(regs); | ||
563 | } | ||
564 | |||
548 | void __init arch_init_irq(void) | 565 | void __init arch_init_irq(void) |
549 | { | 566 | { |
550 | unsigned int irq; | 567 | unsigned int irq; |
@@ -556,7 +573,6 @@ void __init arch_init_irq(void) | |||
556 | crime->soft_int = 0; | 573 | crime->soft_int = 0; |
557 | mace->perif.ctrl.istat = 0; | 574 | mace->perif.ctrl.istat = 0; |
558 | mace->perif.ctrl.imask = 0; | 575 | mace->perif.ctrl.imask = 0; |
559 | set_except_vector(0, ip32_handle_int); | ||
560 | 576 | ||
561 | for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { | 577 | for (irq = 0; irq <= IP32_IRQ_MAX; irq++) { |
562 | hw_irq_controller *controller; | 578 | hw_irq_controller *controller; |