X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fmips-boards%2Fmalta%2Fmalta_int.c;h=d06dc5ad6c9e55edd2284540ea01e729f2678d55;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=33e0f4b2050d5156fe9fcdf36bc442de16bc311a;hpb=daddc0d38b3571bed170afa273a49a0eba090c1e;p=linux-2.6.git diff --git a/arch/mips/mips-boards/malta/malta_int.c b/arch/mips/mips-boards/malta/malta_int.c index 33e0f4b20..d06dc5ad6 100644 --- a/arch/mips/mips-boards/malta/malta_int.c +++ b/arch/mips/mips-boards/malta/malta_int.c @@ -1,6 +1,6 @@ /* * Carsten Langgaard, carstenl@mips.com - * Copyright (C) 2000, 2001 MIPS Technologies, Inc. + * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc. * Copyright (C) 2001 Ralf Baechle * * This program is free software; you can distribute it and/or modify it @@ -21,7 +21,6 @@ * The interrupt controller is located in the South Bridge a PIIX4 device * with two internal 82C95 interrupt controllers. */ -#include #include #include #include @@ -31,6 +30,7 @@ #include #include +#include #include #include #include @@ -38,16 +38,12 @@ #include #include #include +#include extern asmlinkage void mipsIRQ(void); +extern void mips_timer_interrupt(void); -#ifdef CONFIG_KGDB -extern void breakpoint(void); -extern void set_debug_traps(void); -extern int remote_debug; -#endif - -static spinlock_t mips_irq_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(mips_irq_lock); static inline int mips_pcibios_iack(void) { @@ -61,6 +57,7 @@ static inline int mips_pcibios_iack(void) switch(mips_revision_corid) { case MIPS_REVISION_CORID_CORE_MSC: case MIPS_REVISION_CORID_CORE_FPGA2: + case MIPS_REVISION_CORID_CORE_FPGA3: case MIPS_REVISION_CORID_CORE_EMUL_MSC: MSC_READ(MSC01_PCI_IACK, irq); irq &= 0xff; @@ -98,88 +95,86 @@ static inline int mips_pcibios_iack(void) return irq; } -static inline int get_int(int *irq) +static inline int get_int(void) { unsigned long flags; - + int irq; spin_lock_irqsave(&mips_irq_lock, flags); - *irq = mips_pcibios_iack(); + irq = mips_pcibios_iack(); /* - * 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. + * The only way we can decide if an interrupt is spurious + * is by checking the 8259 registers. This needs a spinlock + * on an SMP system, so leave it up to the generic code... */ - if (*irq == 7) - { - outb(PIIX4_OCW3_SEL | PIIX4_OCW3_ISR, - PIIX4_ICTLR1_OCW3); - if (!(inb(PIIX4_ICTLR1_OCW3) & (1 << 7))) { - spin_unlock_irqrestore(&mips_irq_lock, flags); - printk("We got a spurious interrupt from PIIX4.\n"); - atomic_inc(&irq_err_count); - return -1; /* Spurious interrupt. */ - } - } spin_unlock_irqrestore(&mips_irq_lock, flags); - return 0; + return irq; } void malta_hw0_irqdispatch(struct pt_regs *regs) { int irq; - if (get_int(&irq)) - return; /* interrupt has already been cleared */ + irq = get_int(); + if (irq < 0) + return; /* interrupt has already been cleared */ - do_IRQ(irq, regs); + do_IRQ(MALTA_INT_BASE+irq, regs); } void corehi_irqdispatch(struct pt_regs *regs) { - unsigned int data,datahi; - - /* Mask out corehi interrupt. */ - clear_c0_status(IE_IRQ3); + unsigned int intrcause,datalo,datahi; + unsigned int pcimstat, intisr, inten, intpol, intedge, intsteer, pcicmd, pcibadaddr; 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); + + /* Read all the registers and then print them as there is a + problem with interspersed printk's upsetting the Bonito controller. + Do it for the others too. + */ + switch(mips_revision_corid) { case MIPS_REVISION_CORID_CORE_MSC: case MIPS_REVISION_CORID_CORE_FPGA2: - case MIPS_REVISION_CORID_CORE_EMUL_MSC: + case MIPS_REVISION_CORID_CORE_FPGA3: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: + ll_msc_irq(regs); break; case MIPS_REVISION_CORID_QED_RM5261: case MIPS_REVISION_CORID_CORE_LV: case MIPS_REVISION_CORID_CORE_FPGA: case MIPS_REVISION_CORID_CORE_FPGAR2: - data = GT_READ(GT_INTRCAUSE_OFS); - printk("GT_INTRCAUSE = %08x\n", data); - data = GT_READ(0x70); - datahi = GT_READ(0x78); - printk("GT_CPU_ERR_ADDR = %02x%08x\n", datahi, data); + intrcause = GT_READ(GT_INTRCAUSE_OFS); + datalo = GT_READ(GT_CPUERR_ADDRLO_OFS); + datahi = GT_READ(GT_CPUERR_ADDRHI_OFS); + printk("GT_INTRCAUSE = %08x\n", intrcause); + printk("GT_CPUERR_ADDR = %02x%08x\n", datahi, datalo); break; case MIPS_REVISION_CORID_BONITO64: case MIPS_REVISION_CORID_CORE_20K: case MIPS_REVISION_CORID_CORE_EMUL_BON: - 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); + pcibadaddr = BONITO_PCIBADADDR; + pcimstat = BONITO_PCIMSTAT; + intisr = BONITO_INTISR; + inten = BONITO_INTEN; + intpol = BONITO_INTPOL; + intedge = BONITO_INTEDGE; + intsteer = BONITO_INTSTEER; + pcicmd = BONITO_PCICMD; + printk("BONITO_INTISR = %08x\n", intisr); + printk("BONITO_INTEN = %08x\n", inten); + printk("BONITO_INTPOL = %08x\n", intpol); + printk("BONITO_INTEDGE = %08x\n", intedge); + printk("BONITO_INTSTEER = %08x\n", intsteer); + printk("BONITO_PCICMD = %08x\n", pcicmd); + printk("BONITO_PCIBADADDR = %08x\n", pcibadaddr); + printk("BONITO_PCIMSTAT = %08x\n", pcimstat); break; } @@ -187,18 +182,71 @@ void corehi_irqdispatch(struct pt_regs *regs) die("CoreHi interrupt", regs); } -void __init init_IRQ(void) +static struct irqaction i8259irq = { + .handler = no_action, + .name = "XT-PIC cascade" +}; + +static struct irqaction corehi_irqaction = { + .handler = no_action, + .name = "CoreHi" +}; + +msc_irqmap_t __initdata msc_irqmap[] = { + {MSC01C_INT_TMR, MSC01_IRQ_EDGE, 0}, + {MSC01C_INT_PCI, MSC01_IRQ_LEVEL, 0}, +}; +int __initdata msc_nr_irqs = sizeof(msc_irqmap)/sizeof(msc_irqmap_t); + +msc_irqmap_t __initdata msc_eicirqmap[] = { + {MSC01E_INT_SW0, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_SW1, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_I8259A, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_SMI, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_COREHI, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_CORELO, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_TMR, MSC01_IRQ_EDGE, 0}, + {MSC01E_INT_PCI, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_PERFCTR, MSC01_IRQ_LEVEL, 0}, + {MSC01E_INT_CPUCTR, MSC01_IRQ_LEVEL, 0} +}; +int __initdata msc_nr_eicirqs = sizeof(msc_eicirqmap)/sizeof(msc_irqmap_t); + +void __init arch_init_irq(void) { set_except_vector(0, mipsIRQ); - init_generic_irq(); init_i8259_irqs(); -#ifdef CONFIG_KGDB - if (remote_debug) { - set_debug_traps(); - breakpoint(); + if (!cpu_has_veic) + mips_cpu_irq_init (MIPSCPU_INT_BASE); + + switch(mips_revision_corid) { + case MIPS_REVISION_CORID_CORE_MSC: + case MIPS_REVISION_CORID_CORE_FPGA2: + case MIPS_REVISION_CORID_CORE_FPGA3: + case MIPS_REVISION_CORID_CORE_EMUL_MSC: + if (cpu_has_veic) + init_msc_irqs (MSC01E_INT_BASE, msc_eicirqmap, msc_nr_eicirqs); + else + init_msc_irqs (MSC01C_INT_BASE, msc_irqmap, msc_nr_irqs); } -#endif -} + if (cpu_has_veic) { + set_vi_handler (MSC01E_INT_I8259A, malta_hw0_irqdispatch); + set_vi_handler (MSC01E_INT_COREHI, corehi_irqdispatch); + setup_irq (MSC01E_INT_BASE+MSC01E_INT_I8259A, &i8259irq); + setup_irq (MSC01E_INT_BASE+MSC01E_INT_COREHI, &corehi_irqaction); + } + else if (cpu_has_vint) { + set_vi_handler (MIPSCPU_INT_I8259A, malta_hw0_irqdispatch); + set_vi_handler (MIPSCPU_INT_COREHI, corehi_irqdispatch); + setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq); + setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); + } + else { + set_except_vector(0, mipsIRQ); + setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_I8259A, &i8259irq); + setup_irq (MIPSCPU_INT_BASE+MIPSCPU_INT_COREHI, &corehi_irqaction); + } +}