patch-2.4.19 linux-2.4.19/arch/mips/mips-boards/malta/malta_int.c
Next file: linux-2.4.19/arch/mips/mips-boards/malta/malta_setup.c
Previous file: linux-2.4.19/arch/mips/mips-boards/malta/Makefile
Back to the patch index
Back to the overall index
- Lines: 316
- Date:
Fri Aug 2 17:39:43 2002
- Orig file:
linux-2.4.18/arch/mips/mips-boards/malta/malta_int.c
- Orig date:
Sun Sep 9 10:43:02 2001
diff -urN linux-2.4.18/arch/mips/mips-boards/malta/malta_int.c linux-2.4.19/arch/mips/mips-boards/malta/malta_int.c
@@ -36,40 +36,290 @@
#include <asm/mips-boards/piix4.h>
#include <asm/gt64120.h>
#include <asm/mips-boards/generic.h>
+#include <asm/mips-boards/msc01_pci.h>
extern asmlinkage void mipsIRQ(void);
+extern asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+extern void init_i8259_irqs (void);
+
+void enable_mips_irq(unsigned int irq);
+void disable_mips_irq(unsigned int irq);
+
+static spinlock_t mips_irq_lock = SPIN_LOCK_UNLOCKED;
+
+static void end_mips_irq (unsigned int irq)
+{
+ if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+ enable_mips_irq(irq);
+}
+
+#define shutdown_mips_irq disable_mips_irq
+
+void mask_and_ack_mips_irq(unsigned int irq);
+
+static unsigned int startup_mips_irq(unsigned int irq)
+{
+ enable_mips_irq(irq);
+
+ return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type mips_irq_type = {
+ "XT-PIC",
+ startup_mips_irq,
+ shutdown_mips_irq,
+ enable_mips_irq,
+ disable_mips_irq,
+ mask_and_ack_mips_irq,
+ end_mips_irq,
+ NULL
+};
+
+/*
+ * This contains the interrupt mask for both 82C59 interrupt controllers.
+ */
+static unsigned int cached_int_mask = 0xffff;
+
+void disable_mips_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ if(irq_nr >= MALTAINT_END) {
+ printk("whee, invalid irq_nr %d\n", irq_nr);
+ panic("IRQ, you lose...");
+ }
+
+ spin_lock_irqsave(&mips_irq_lock, flags);
+ cached_int_mask |= (1 << irq_nr);
+ if (irq_nr & 8) {
+ outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+ } else {
+ outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+ }
+ spin_unlock_irqrestore(&mips_irq_lock, flags);
+}
+
+void enable_mips_irq(unsigned int irq_nr)
+{
+ unsigned long flags;
+
+ if(irq_nr >= MALTAINT_END) {
+ printk("whee, invalid irq_nr %d\n", irq_nr);
+ panic("IRQ, you lose...");
+ }
+
+ spin_lock_irqsave(&mips_irq_lock, flags);
+ cached_int_mask &= ~(1 << irq_nr);
+ if (irq_nr & 8) {
+ outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+
+ /* Enable irq 2 (cascade interrupt). */
+ cached_int_mask &= ~(1 << 2);
+ outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+ } else {
+ outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+ }
+ spin_unlock_irqrestore(&mips_irq_lock, flags);
+}
+
+void mask_and_ack_mips_irq(unsigned int irq)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&mips_irq_lock, flags);
+ if (irq & 8) {
+ /* Non specific EOI to cascade */
+ outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI | PIIX4_OCW2_ILS_2,
+ PIIX4_ICTLR1_OCW2);
+
+ outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR2_OCW2);
+ } else {
+ outb(PIIX4_OCW2_SEL | PIIX4_OCW2_NSEOI, PIIX4_ICTLR1_OCW2);
+ }
+ spin_unlock_irqrestore(&mips_irq_lock, flags);
+}
+
+static inline int get_int(int *irq)
+{
+ unsigned char irr;
+
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_MSC:
+ /*
+ * Determine highest priority pending interrupt by performing
+ * a PCI Interrupt Acknowledge cycle.
+ */
+ if (mips_revision_corid == MIPS_REVISION_CORID_CORE_MSC)
+ MSC_READ(MSC01_PCI_IACK, *irq);
+ else
+ GT_READ(GT_PCI0_IACK_OFS, *irq);
+ *irq &= 0xFF;
+
+ /*
+ * IRQ7 is used to detect spurious interrupts.
+ * The interrupt acknowledge cycle returns IRQ7, if no
+ * interrupts is requested.
+ * We can differentiate between this situation and a
+ * "Normal" IRQ7 by reading the ISR.
+ */
+ if (*irq == 7)
+ {
+ outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR,
+ PIIX4_ICTLR1_OCW3);
+ if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) {
+ printk("We got a spurious interrupt from PIIX4.\n");
+ atomic_inc(&irq_err_count);
+ return -1; /* Spurious interrupt. */
+ }
+ }
+ break;
+
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ /*
+ * Determine highest priority pending interrupt by reading
+ * the IRR register of controller 1.
+ */
+
+ outb(PIIX4_OCW3_SEL | PIIX4_OCW3_IRR, PIIX4_ICTLR1_OCW3);
+ irr = inb(PIIX4_ICTLR1_OCW3) & ~(cached_int_mask & 0xff);
+
+ if (!irr) {
+ printk("We got a spurious interrupt from PIIX4.\n");
+ atomic_inc(&irq_err_count);
+ return -1; /* Spurious interrupt. */
+ }
+ *irq = 0;
+ while ((*irq < 7) && !(irr & 0x01)) {
+ (*irq)++;
+ irr >>= 1;
+ }
+
+ if (*irq == 2)
+ {
+ /*
+ * Determine highest priority pending interrupt by
+ * reading the IRR register of controller 1.
+ */
+ outb(PIIX4_OCW3_SEL | PIIX4_OCW3_IRR,
+ PIIX4_ICTLR2_OCW3);
+ irr = inb(PIIX4_ICTLR2_OCW3) &
+ ~((cached_int_mask >> 8) & 0xff);
+
+ *irq = 8;
+ while ((*irq < 15) && !(irr & 0x01)) {
+ (*irq)++;
+ irr >>= 1;
+ }
+ }
+ break;
+ default:
+ printk("Unknown Core card, don't know the system controller.\n");
+ return -1;
+ }
+
+ return 0;
+}
void malta_hw0_irqdispatch(struct pt_regs *regs)
{
int irq;
+ struct irqaction *action;
- /*
- * Determine highest priority pending interrupt by performing a PCI
- * Interrupt Acknowledge cycle.
- */
- GT_READ(GT_PCI0_IACK_OFS, irq);
- irq &= 0xFF;
-
- /*
- * IRQ7 is used to detect spurious interrupts. The interrupt
- * acknowledge cycle returns IRQ7, if no interrupts is requested. We
- * can differentiate between this situation and a "normal" IRQ7 by
- * reading the ISR.
- */
- if (irq == 7) {
- outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, PIIX4_ICTLR1_OCW3);
- if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7)))
- return; /* Spurious interrupt. */
- }
+ if (get_int(&irq))
+ return; /* interrupt has already been cleared */
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ action = irq_desc[irq].action;
+ if (!action)
+ return;
+ action->flags |= SA_INTERRUPT;
+ break;
+ }
+
do_IRQ(irq, regs);
}
+void corehi_irqdispatch(struct pt_regs *regs)
+{
+ unsigned int data,datahi;
+
+ printk("CoreHI interrupt, shouldn't happen, so we die here!!!\n");
+ printk("epc : %08lx\nStatus: %08lx\nCause : %08lx\nbadVaddr : %08lx\n"
+, regs->cp0_epc, regs->cp0_status, regs->cp0_cause, regs->cp0_badvaddr);
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_CORE_MSC:
+ break;
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ GT_READ(GT_INTRCAUSE_OFS, data);
+ printk("GT_INTRCAUSE = %08x\n", data);
+ GT_READ(0x70, data);
+ GT_READ(0x78, datahi);
+ printk("GT_CPU_ERR_ADDR = %0x2%08x\n", datahi,data);
+ break;
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ data = BONITO_INTISR;
+ printk("BONITO_INTISR = %08x\n", data);
+ data = BONITO_INTEN;
+ printk("BONITO_INTEN = %08x\n", data);
+ data = BONITO_INTPOL;
+ printk("BONITO_INTPOL = %08x\n", data);
+ data = BONITO_INTEDGE;
+ printk("BONITO_INTEDGE = %08x\n", data);
+ data = BONITO_INTSTEER;
+ printk("BONITO_INTSTEER = %08x\n", data);
+ data = BONITO_PCICMD;
+ printk("BONITO_PCICMD = %08x\n", data);
+ break;
+ }
+
+ /* We die here*/
+ die("CoreHi interrupt", regs);
+ while (1) ;
+}
+
void __init init_IRQ(void)
{
+ unsigned int i;
+
set_except_vector(0, mipsIRQ);
init_generic_irq();
- init_i8259_irqs();
+
+ switch(mips_revision_corid) {
+ case MIPS_REVISION_CORID_QED_RM5261:
+ case MIPS_REVISION_CORID_CORE_LV:
+ case MIPS_REVISION_CORID_CORE_FPGA:
+ case MIPS_REVISION_CORID_CORE_MSC:
+ init_i8259_irqs();
+ break;
+ case MIPS_REVISION_CORID_BONITO64:
+ case MIPS_REVISION_CORID_CORE_20K:
+ /*
+ * Mask out all interrupt by writing "1" to all bit position
+ * in the IMR register.
+ */
+ outb(cached_int_mask & 0xff, PIIX4_ICTLR1_OCW1);
+ outb((cached_int_mask >> 8) & 0xff, PIIX4_ICTLR2_OCW1);
+
+ for (i = 0; i < 16; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ irq_desc[i].action = 0;
+ irq_desc[i].depth = 1;
+ irq_desc[i].handler = &mips_irq_type;
+ }
+ break;
+ default:
+ printk("Unknown Core card, don't know the system controller.\n");
+ return;
+ }
#ifdef CONFIG_REMOTE_DEBUG
if (remote_debug) {
@@ -78,3 +328,5 @@
}
#endif
}
+
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)