aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/sgi-ip32
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/sgi-ip32')
-rw-r--r--arch/mips/sgi-ip32/Makefile2
-rw-r--r--arch/mips/sgi-ip32/ip32-irq-glue.S86
-rw-r--r--arch/mips/sgi-ip32/ip32-irq.c44
3 files changed, 31 insertions, 101 deletions
diff --git a/arch/mips/sgi-ip32/Makefile b/arch/mips/sgi-ip32/Makefile
index 470898f4afe1..530bf848c3d0 100644
--- a/arch/mips/sgi-ip32/Makefile
+++ b/arch/mips/sgi-ip32/Makefile
@@ -3,7 +3,7 @@
3# under Linux. 3# under Linux.
4# 4#
5 5
6obj-y += ip32-berr.o ip32-irq.o ip32-irq-glue.o ip32-setup.o ip32-reset.o \ 6obj-y += ip32-berr.o ip32-irq.o ip32-setup.o ip32-reset.o \
7 crime.o ip32-memory.o 7 crime.o ip32-memory.o
8 8
9EXTRA_AFLAGS := $(CFLAGS) 9EXTRA_AFLAGS := $(CFLAGS)
diff --git a/arch/mips/sgi-ip32/ip32-irq-glue.S b/arch/mips/sgi-ip32/ip32-irq-glue.S
deleted file mode 100644
index 200924e1c4f5..000000000000
--- a/arch/mips/sgi-ip32/ip32-irq-glue.S
+++ /dev/null
@@ -1,86 +0,0 @@
1/*
2 * Low level interrupt handler for the SGI O2 aka IP32 aka Moosehead
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 2000 Harald Koerfgen
9 * Copyright (C) 2001 Keith M Wesolowski
10 */
11#include <asm/asm.h>
12#include <asm/regdef.h>
13#include <asm/mipsregs.h>
14#include <asm/stackframe.h>
15#include <asm/addrspace.h>
16
17 .text
18 .set noreorder
19 .set noat
20 .align 5
21 NESTED(ip32_handle_int, PT_SIZE, ra)
22 .set noat
23 SAVE_ALL
24 CLI # TEST: interrupts should be off
25 .set at
26 .set noreorder
27
28 mfc0 s0,CP0_CAUSE
29
30 andi t1, s0, IE_IRQ0
31 bnez t1, handle_irq0
32 andi t1, s0, IE_IRQ1
33 bnez t1, handle_irq1
34 andi t1, s0, IE_IRQ2
35 bnez t1, handle_irq2
36 andi t1, s0, IE_IRQ3
37 bnez t1, handle_irq3
38 andi t1, s0, IE_IRQ4
39 bnez t1, handle_irq4
40 andi t1, s0, IE_IRQ5
41 bnez t1, handle_irq5
42 nop
43
44 /* Either someone has triggered the "software interrupts"
45 * or we lost an interrupt somehow. Ignore it.
46 */
47 j ret_from_irq
48 nop
49
50handle_irq0:
51 jal ip32_irq0
52 move a0, sp
53 j ret_from_irq
54 nop
55
56handle_irq1:
57 jal ip32_irq1
58 move a0, sp
59 j ret_from_irq
60 nop
61
62handle_irq2:
63 jal ip32_irq2
64 move a0, sp
65 j ret_from_irq
66 nop
67
68handle_irq3:
69 jal ip32_irq3
70 move a0, sp
71 j ret_from_irq
72 nop
73
74handle_irq4:
75 jal ip32_irq4
76 move a0, sp
77 j ret_from_irq
78 nop
79
80handle_irq5:
81 jal ip32_irq5
82 move a0, sp
83 j ret_from_irq
84 nop
85
86 END(ip32_handle_int)
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 */
32static void inline flush_crime_bus(void) 32static void inline flush_crime_bus(void)
33{ 33{
34 volatile unsigned long junk = crime->control; 34 crime->control;
35} 35}
36 36
37static void inline flush_mace_bus(void) 37static 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,
130struct irqaction cpuerr_irq = { crime_cpuerr_intr, SA_INTERRUPT, 130struct 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
133extern 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 */
506void ip32_irq0(struct pt_regs *regs) 504static 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
523void ip32_irq1(struct pt_regs *regs) 522static void ip32_irq1(struct pt_regs *regs)
524{ 523{
525 ip32_unknown_interrupt(regs); 524 ip32_unknown_interrupt(regs);
526} 525}
527 526
528void ip32_irq2(struct pt_regs *regs) 527static void ip32_irq2(struct pt_regs *regs)
529{ 528{
530 ip32_unknown_interrupt(regs); 529 ip32_unknown_interrupt(regs);
531} 530}
532 531
533void ip32_irq3(struct pt_regs *regs) 532static void ip32_irq3(struct pt_regs *regs)
534{ 533{
535 ip32_unknown_interrupt(regs); 534 ip32_unknown_interrupt(regs);
536} 535}
537 536
538void ip32_irq4(struct pt_regs *regs) 537static void ip32_irq4(struct pt_regs *regs)
539{ 538{
540 ip32_unknown_interrupt(regs); 539 ip32_unknown_interrupt(regs);
541} 540}
542 541
543void ip32_irq5(struct pt_regs *regs) 542static 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
547asmlinkage 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
548void __init arch_init_irq(void) 565void __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;