summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-10-10 23:49:14 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-10-10 23:49:14 +0000
commitb4b4c1bb8d1207ae76e63d5c273a27b03cad3ca2 (patch)
treeb1e157cd0734d76c6195055f4623de890fa7fd04 /arch
parentdab21d5b9d53e993b96589861e63a63ac85f71c2 (diff)
SNI updates, the first in a century ...
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/sni/Makefile2
-rw-r--r--arch/mips/sni/int-handler.S84
-rw-r--r--arch/mips/sni/irq.c160
-rw-r--r--arch/mips/sni/setup.c57
4 files changed, 178 insertions, 125 deletions
diff --git a/arch/mips/sni/Makefile b/arch/mips/sni/Makefile
index b5091e159..6589a47c6 100644
--- a/arch/mips/sni/Makefile
+++ b/arch/mips/sni/Makefile
@@ -14,7 +14,7 @@
all: sni.o
O_TARGET := sni.o
-O_OBJS := dma.o int-handler.o io.o pci.o pcimt_scache.o reset.o setup.o
+O_OBJS := dma.o int-handler.o io.o irq.o pci.o pcimt_scache.o reset.o setup.o
int-handler.o: int-handler.S
diff --git a/arch/mips/sni/int-handler.S b/arch/mips/sni/int-handler.S
index 57dfd661f..15f412ec5 100644
--- a/arch/mips/sni/int-handler.S
+++ b/arch/mips/sni/int-handler.S
@@ -1,8 +1,7 @@
-/* $Id: int-handler.S,v 1.4 1999/01/04 16:03:58 ralf Exp $
- *
+/*
* SNI RM200 PCI specific interrupt handler code.
*
- * Copyright (C) 1994 - 1997 by Ralf Baechle
+ * Copyright (C) 1994, 95, 96, 97, 98, 1999, 2000 by Ralf Baechle
*/
#include <asm/asm.h>
#include <asm/mipsregs.h>
@@ -37,22 +36,14 @@ led_cache: .byte 0
mfc0 t1, CP0_CAUSE
and t0, t1
- /* The following interrupt dispatch tests for hwint 1 /
- EISA bridge first such that the timer interrupt get the
- highest priority. */
- andi t1, t0, 0x0800 # hardware interrupt 1
- bnez t1, hwint1
- andi t1, t0, 0x4000 # hardware interrupt 4
- bnez t1, hwint4
-
+ andi t1, t0, 0x4a00 # hardware interrupt 1
+ bnez t1, _hwint134
andi t1, t0, 0x1000 # hardware interrupt 2
- bnez t1, hwint2
- andi t1, t0, 0x2000 # hardware interrupt 3
- bnez t1, hwint3
+ bnez t1, _hwint2
andi t1, t0, 0x8000 # hardware interrupt 5
- bnez t1, hwint5
+ bnez t1, _hwint5
andi t1, t0, 0x0400 # hardware interrupt 0
- bnez t1, hwint0
+ bnez t1, _hwint0
nop
j return # spurious interrupt
@@ -60,66 +51,23 @@ led_cache: .byte 0
##############################################################################
-swint0: PANIC("swint0")
-swint1: PANIC("swint1")
-
- /* ------------------------------------------------------------------------ */
-
-/* hwint1 deals with EISA and SCSI interrupts. */
-hwint1: lbu s0, PCIMT_CSITPEND
-
- andi t1, s0, 0x20
- beqz t1, 1f
- andi s1, s0, 0x40
- lbu a0, PCIMT_INT_ACKNOWLEDGE # IACK cycle
- xori t0, a0, 0xff
- beqz t0, 1f # spurious interrupt?
- nop
- jal i8259_do_irq # call real handler
- move a1, sp
-
-1: bnez s1, 1f
- li a0, PCIMT_IRQ_SCSI
- jal do_IRQ
- move a1, sp
-
-1: lui t0, %hi(PCIMT_CSITPEND)
- j ret_from_irq
- lbu zero, %lo(PCIMT_CSITPEND)(t0)
-
- /* ------------------------------------------------------------------------ */
-
/* hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
button interrupts. */
-hwint0: PANIC("Received int0 but no handler yet ...\n")
-1: j 1b
- nop
-
-go_spurious: j spurious_interrupt # we got fooled
- nop
-
-/* hwint4 is used for only the onboard PCnet 32. */
-hwint4: mfc0 s0, CP0_STATUS
- ori t0, s0, 0x4000
- xori t0, 0x4000
- mtc0 t0, CP0_STATUS
-
- li a0, PCIMT_IRQ_ETHERNET
- jal do_IRQ
+_hwint0: jal pciasic_hwint0
move a1, sp
- mtc0 s0, CP0_STATUS
+/*
+ * hwint 1 deals with EISA and SCSI interrupts,
+ * hwint 3 should deal with the PCI A - D interrupts,
+ * hwint 4 is used for only the onboard PCnet 32.
+ */
+_hwint134: jal pciasic_hwint134
- j ret_from_irq
- nop
/* This interrupt was used for the com1 console on the first prototypes. */
-hwint2: PANIC("hwint2 and no handler yet")
-
-/* hwint3 should deal with the PCI A - D interrupts. */
-hwint3: PANIC("hwint3 and no handler yet")
+_hwint2: jal pciasic_hwint2
/* hwint5 is the r4k count / compare interrupt */
-hwint5: PANIC("hwint5 and no handler yet")
+_hwint5: jal pciasic_hwint5
END(sni_rm200_pci_handle_int)
diff --git a/arch/mips/sni/irq.c b/arch/mips/sni/irq.c
new file mode 100644
index 000000000..8af85d13f
--- /dev/null
+++ b/arch/mips/sni/irq.c
@@ -0,0 +1,160 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/sni.h>
+
+spinlock_t pciasic_lock = SPIN_LOCK_UNLOCKED;
+
+extern asmlinkage void sni_rm200_pci_handle_int(void);
+extern void do_IRQ(int irq, struct pt_regs *regs);
+extern void i8259_do_irq(int irq, struct pt_regs *regs);
+
+static void enable_pciasic_irq(unsigned int irq);
+
+static unsigned int startup_pciasic_irq(unsigned int irq)
+{
+ enable_pciasic_irq(irq);
+ return 0; /* never anything pending */
+}
+
+#define shutdown_pciasic_irq disable_pciasic_irq
+
+void disable_pciasic_irq(unsigned int irq)
+{
+ unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
+ unsigned long flags;
+
+ spin_lock_irqsave(&pciasic_lock, flags);
+ *(volatile u8 *) PCIMT_IRQSEL &= mask;
+ spin_unlock_irqrestore(&pciasic_lock, flags);
+}
+
+static void enable_pciasic_irq(unsigned int irq)
+{
+ unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
+ unsigned long flags;
+
+ spin_lock_irqsave(&pciasic_lock, flags);
+ *(volatile u8 *) PCIMT_IRQSEL |= mask;
+ spin_unlock_irqrestore(&pciasic_lock, flags);
+}
+
+#define mask_and_ack_pciasic_irq disable_pciasic_irq
+
+static void end_pciasic_irq(unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_pciasic_irq(irq);
+}
+
+static struct hw_interrupt_type pciasic_irq_type = {
+ "PCIASIC",
+ startup_pciasic_irq,
+ shutdown_pciasic_irq,
+ enable_pciasic_irq,
+ disable_pciasic_irq,
+ mask_and_ack_pciasic_irq,
+ end_pciasic_irq,
+ NULL
+};
+
+/*
+ * hwint0 should deal with MP agent, ASIC PCI, EISA NMI and debug
+ * button interrupts. Later ...
+ */
+void pciasic_hwint0(struct pt_regs *regs)
+{
+ panic("Received int0 but no handler yet ...");
+}
+
+/* This interrupt was used for the com1 console on the first prototypes. */
+void pciasic_hwint2(struct pt_regs *regs)
+{
+ /* I think this shouldn't happen on production machines. */
+ panic("hwint2 and no handler yet");
+}
+
+/* hwint5 is the r4k count / compare interrupt */
+void pciasic_hwint5(struct pt_regs *regs)
+{
+ panic("hwint5 and no handler yet");
+}
+
+static inline int ls1bit8(unsigned int x)
+{
+ int b = 8, s;
+
+ x <<= 24;
+ s = 4; if ((x & 0x0f) == 0) s = 0; b -= s; x <<= s;
+ s = 2; if ((x & 0x03) == 0) s = 0; b -= s; x <<= s;
+ s = 1; if ((x & 0x01) == 0) s = 0; b -= s;
+
+ return b;
+}
+
+/*
+ * hwint 1 deals with EISA and SCSI interrupts,
+ * hwint 3 should deal with the PCI A - D interrupts,
+ * hwint 4 is used for only the onboard PCnet 32.
+ */
+void pciasic_hwint134(struct pt_regs *regs)
+{
+ u8 pend = *(volatile char *)PCIMT_CSITPEND;
+ int irq;
+
+ irq = PCIMT_IRQ_INT2 + ls1bit8(pend);
+ if (irq == PCIMT_IRQ_EISA) {
+ pend = *(volatile char *)PCIMT_INT_ACKNOWLEDGE;
+ if (!(pend ^ 0xff))
+ return;
+ }
+ do_IRQ(irq, regs);
+ return;
+}
+
+void __init init_pciasic(void)
+{
+ unsigned int flags;
+
+ spin_lock_irqsave(&pciasic_lock, flags);
+ * (volatile u8 *) PCIMT_IRQSEL =
+ IT_EISA | IT_INTA | IT_INTB | IT_INTC | IT_INTD;
+ spin_unlock_irqrestore(&pciasic_lock, flags);
+}
+
+/*
+ * On systems with i8259-style interrupt controllers we assume for
+ * driver compatibility reasons interrupts 0 - 15 to be the i8295
+ * interrupts even if the hardware uses a different interrupt numbering.
+ */
+void __init init_IRQ (void)
+{
+ int i;
+
+ set_except_vector(0, sni_rm200_pci_handle_int);
+
+ init_generic_irq();
+ init_i8259_irqs(); /* Integrated i8259 */
+ init_pciasic();
+
+ /* Actually we've got more interrupts to handle ... */
+ for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_ETHERNET; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &pciasic_irq_type;
+ }
+}
diff --git a/arch/mips/sni/setup.c b/arch/mips/sni/setup.c
index f174c7efd..db053720c 100644
--- a/arch/mips/sni/setup.c
+++ b/arch/mips/sni/setup.c
@@ -31,18 +31,6 @@
#include <asm/reboot.h>
#include <asm/sni.h>
-/*
- * Initial irq handlers.
- */
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL};
-
-extern asmlinkage void sni_rm200_pci_handle_int(void);
-
extern void sni_machine_restart(char *command);
extern void sni_machine_halt(void);
extern void sni_machine_power_off(void);
@@ -51,20 +39,6 @@ extern struct ide_ops std_ide_ops;
extern struct rtc_ops std_rtc_ops;
extern struct kbd_ops std_kbd_ops;
-static void __init sni_irq_setup(void)
-{
- set_except_vector(0, sni_rm200_pci_handle_int);
- request_region(0x20,0x20, "pic1");
- request_region(0xa0,0x20, "pic2");
- i8259_setup_irq(2, &irq2);
- /*
- * IRQ0 seems to be the irq for PC style stuff.
- * I don't know how to handle the debug button interrupt, so
- * don't use this button yet or bad things happen ...
- */
- set_cp0_status(ST0_IM, IE_IRQ1 | IE_IRQ3 | IE_IRQ4);
-}
-
void (*board_time_init)(struct irqaction *irq);
static void __init sni_rm200_pci_time_init(struct irqaction *irq)
@@ -73,7 +47,7 @@ static void __init sni_rm200_pci_time_init(struct irqaction *irq)
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
- i8259_setup_irq(0, irq);
+ setup_irq(0, irq);
}
unsigned char aux_device_present;
@@ -108,38 +82,9 @@ int __init page_is_ram(unsigned long pagenr)
void __init sni_rm200_pci_setup(void)
{
-#if 0 /* XXX Tag me deeper */
- tag *atag;
-
- /*
- * We just check if a tag_screen_info can be gathered
- * in setup_arch(), if yes we don't proceed futher...
- */
- atag = bi_TagFind(tag_screen_info);
- if (!atag) {
- /*
- * If no, we try to find the tag_arc_displayinfo which is
- * always created by Milo for an ARC box (for now Milo only
- * works on ARC boxes :) -Stoned.
- */
- atag = bi_TagFind(tag_arcdisplayinfo);
- if (atag) {
- screen_info.orig_x =
- ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x;
- screen_info.orig_y =
- ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y;
- screen_info.orig_video_cols =
- ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns;
- screen_info.orig_video_lines =
- ((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines;
- }
- }
-#endif
-
sni_pcimt_detect();
sni_pcimt_sc_init();
- irq_setup = sni_irq_setup;
mips_io_port_base = SNI_PORT_BASE;
/*