Tidy up the Cobalt interrupt handling code. -- Index: linux/include/asm-mips/cobalt/cobalt.h =================================================================== --- linux.orig/include/asm-mips/cobalt/cobalt.h 2005-03-04 15:13:37.000000000 +0000 +++ linux/include/asm-mips/cobalt/cobalt.h 2005-04-06 22:43:05.000000000 +0100 @@ -25,15 +25,17 @@ /* * CPU IRQs are 16 ... 23 */ -#define COBALT_TIMER_IRQ 18 -#define COBALT_SCC_IRQ 19 /* pre-production has 85C30 */ -#define COBALT_RAQ_SCSI_IRQ 19 -#define COBALT_ETH0_IRQ 19 -#define COBALT_QUBE1_ETH0_IRQ 20 -#define COBALT_ETH1_IRQ 20 -#define COBALT_SERIAL_IRQ 21 -#define COBALT_SCSI_IRQ 21 -#define COBALT_VIA_IRQ 22 /* Chained to VIA ISA bridge */ +#define COBALT_CPU_IRQ 16 + +#define COBALT_GALILEO_IRQ (COBALT_CPU_IRQ + 2) +#define COBALT_SCC_IRQ (COBALT_CPU_IRQ + 3) /* pre-production has 85C30 */ +#define COBALT_RAQ_SCSI_IRQ (COBALT_CPU_IRQ + 3) +#define COBALT_ETH0_IRQ (COBALT_CPU_IRQ + 3) +#define COBALT_QUBE1_ETH0_IRQ (COBALT_CPU_IRQ + 4) +#define COBALT_ETH1_IRQ (COBALT_CPU_IRQ + 4) +#define COBALT_SERIAL_IRQ (COBALT_CPU_IRQ + 5) +#define COBALT_SCSI_IRQ (COBALT_CPU_IRQ + 5) +#define COBALT_VIA_IRQ (COBALT_CPU_IRQ + 6) /* Chained to VIA ISA bridge */ /* * PCI configuration space manifest constants. These are wired into @@ -84,7 +86,8 @@ *(volatile unsigned int *) GALILEO_REG(port) = (val); \ } while (0) -#define GALILEO_T0EXP 0x0100 +#define GALILEO_INTR_T0EXP (1 << 8) + #define GALILEO_ENTC0 0x01 #define GALILEO_SELTC0 0x02 Index: linux/arch/mips/cobalt/setup.c =================================================================== --- linux.orig/arch/mips/cobalt/setup.c 2005-03-04 15:13:37.000000000 +0000 +++ linux/arch/mips/cobalt/setup.c 2005-04-06 22:43:05.000000000 +0100 @@ -50,16 +50,17 @@ static void __init cobalt_timer_setup(struct irqaction *irq) { - /* Load timer value for 1KHz */ + /* Load timer value for 1KHz (TCLK is 50MHz) */ GALILEO_OUTL(50*1000*1000 / 1000, GT_TC0_OFS); - /* Register our timer interrupt */ - setup_irq(COBALT_TIMER_IRQ, irq); + /* Enable timer */ + GALILEO_OUTL(GALILEO_ENTC0 | GALILEO_SELTC0, GT_TC_CONTROL_OFS); - /* Enable timer ints */ - GALILEO_OUTL((GALILEO_ENTC0 | GALILEO_SELTC0), GT_TC_CONTROL_OFS); - /* Unmask timer int */ - GALILEO_OUTL(GALILEO_T0EXP, GT_INTRMASK_OFS); + /* Register interrupt */ + setup_irq(COBALT_GALILEO_IRQ, irq); + + /* Enable interrupt */ + GALILEO_OUTL(GALILEO_INTR_T0EXP | GALILEO_INL(GT_INTRMASK_OFS), GT_INTRMASK_OFS); } extern struct pci_ops gt64111_pci_ops; Index: linux/arch/mips/cobalt/irq.c =================================================================== --- linux.orig/arch/mips/cobalt/irq.c 2005-02-21 16:41:55.000000000 +0000 +++ linux/arch/mips/cobalt/irq.c 2005-04-06 22:43:34.000000000 +0100 @@ -43,49 +43,63 @@ * 15 - IDE1 */ -asmlinkage void cobalt_irq(struct pt_regs *regs) +static inline void galileo_irq(struct pt_regs *regs) { - unsigned int pending = read_c0_status() & read_c0_cause(); + unsigned int mask, pending; - if (pending & CAUSEF_IP2) { /* int 18 */ - unsigned long irq_src = GALILEO_INL(GT_INTRCAUSE_OFS); + mask = GALILEO_INL(GT_INTRMASK_OFS); + pending = GALILEO_INL(GT_INTRCAUSE_OFS) & mask; - /* Check for timer irq ... */ - if (irq_src & GALILEO_T0EXP) { - /* Clear the int line */ - GALILEO_OUTL(0, GT_INTRCAUSE_OFS); - do_IRQ(COBALT_TIMER_IRQ, regs); - } - return; - } + if (pending & GALILEO_INTR_T0EXP) { - if (pending & CAUSEF_IP6) { /* int 22 */ - int irq = i8259_irq(); + GALILEO_OUTL(~GALILEO_INTR_T0EXP, GT_INTRCAUSE_OFS); + do_IRQ(COBALT_GALILEO_IRQ, regs); - if (irq >= 0) - do_IRQ(irq, regs); - return; - } + } else { - if (pending & CAUSEF_IP3) { /* int 19 */ - do_IRQ(COBALT_ETH0_IRQ, regs); - return; + GALILEO_OUTL(mask & ~pending, GT_INTRMASK_OFS); + printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending); } +} - if (pending & CAUSEF_IP4) { /* int 20 */ - do_IRQ(COBALT_ETH1_IRQ, regs); - return; - } +static inline void via_pic_irq(struct pt_regs *regs) +{ + int irq; - if (pending & CAUSEF_IP5) { /* int 21 */ - do_IRQ(COBALT_SERIAL_IRQ, regs); - return; - } + irq = i8259_irq(); + if (irq >= 0) + do_IRQ(irq, regs); +} - if (pending & CAUSEF_IP7) { /* int 23 */ - do_IRQ(23, regs); - return; - } +asmlinkage void cobalt_irq(struct pt_regs *regs) +{ + unsigned pending; + + pending = read_c0_status() & read_c0_cause(); + + if (pending & CAUSEF_IP2) /* COBALT_GALILEO_IRQ (18) */ + + galileo_irq(regs); + + else if (pending & CAUSEF_IP6) /* COBALT_VIA_IRQ (22) */ + + via_pic_irq(regs); + + else if (pending & CAUSEF_IP3) /* COBALT_ETH0_IRQ (19) */ + + do_IRQ(COBALT_CPU_IRQ + 3, regs); + + else if (pending & CAUSEF_IP4) /* COBALT_ETH1_IRQ (20) */ + + do_IRQ(COBALT_CPU_IRQ + 4, regs); + + else if (pending & CAUSEF_IP5) /* COBALT_SERIAL_IRQ (21) */ + + do_IRQ(COBALT_CPU_IRQ + 5, regs); + + else if (pending & CAUSEF_IP7) /* IRQ 23 */ + + do_IRQ(COBALT_CPU_IRQ + 7, regs); } static struct irqaction irq_via = { @@ -94,10 +108,16 @@ void __init arch_init_irq(void) { + /* + * Mask all Galileo interrupts. The Galileo + * handler is set in cobalt_timer_setup() + */ + GALILEO_OUTL(0, GT_INTRMASK_OFS); + set_except_vector(0, cobalt_handle_int); init_i8259_irqs(); /* 0 ... 15 */ - mips_cpu_irq_init(16); /* 16 ... 23 */ + mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */ /* * Mask all cpu interrupts