diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-10-10 23:49:14 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-10-10 23:49:14 +0000 |
commit | b4b4c1bb8d1207ae76e63d5c273a27b03cad3ca2 (patch) | |
tree | b1e157cd0734d76c6195055f4623de890fa7fd04 /arch | |
parent | dab21d5b9d53e993b96589861e63a63ac85f71c2 (diff) |
SNI updates, the first in a century ...
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/sni/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/sni/int-handler.S | 84 | ||||
-rw-r--r-- | arch/mips/sni/irq.c | 160 | ||||
-rw-r--r-- | arch/mips/sni/setup.c | 57 |
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; /* |