Hi Ralf, This patch has added common IRQ routines for GT64111/GT64120. Yoichi Signed-off-by: Yoichi Yuasa <yoichi_yuasa@xxxxxxxxxxxxxx> diff -pruN -X mips/Documentation/dontdiff mips-orig/arch/mips/gt64120/cobalt/irq.c mips/arch/mips/gt64120/cobalt/irq.c --- mips-orig/arch/mips/gt64120/cobalt/irq.c 2006-08-18 22:16:52.068534750 +0900 +++ mips/arch/mips/gt64120/cobalt/irq.c 2006-08-17 22:59:36.226694250 +0900 @@ -7,11 +7,10 @@ * * Copyright (C) 1995, 1996, 1997, 2003 by Ralf Baechle */ -#include <linux/kernel.h> #include <linux/init.h> -#include <linux/irq.h> #include <linux/interrupt.h> -#include <linux/pci.h> +#include <linux/irq.h> +#include <linux/kernel.h> #include <asm/i8259.h> #include <asm/irq_cpu.h> @@ -37,37 +36,11 @@ * The VIA chip is a master/slave 8259 setup and has the following interrupts: * * 8 - RTC - * 9 - PCI + * 9 - PCI slot * 14 - IDE0 * 15 - IDE1 */ -static inline void galileo_irq(struct pt_regs *regs) -{ - unsigned int mask, pending, devfn; - - mask = GT_READ(GT_INTRMASK_OFS); - pending = GT_READ(GT_INTRCAUSE_OFS) & mask; - - if (pending & GALILEO_INTR_T3EXP) { - - GT_WRITE(GT_INTRCAUSE_OFS, ~GALILEO_INTR_T3EXP); - do_IRQ(COBALT_GALILEO_IRQ, regs); - - } else if (pending & GALILEO_INTR_RETRY_CTR) { - - devfn = GT_READ(GT_PCI0_CFGADDR_OFS) >> 8; - GT_WRITE(GT_INTRCAUSE_OFS, ~GALILEO_INTR_RETRY_CTR); - printk(KERN_WARNING "Galileo: PCI retry count exceeded (%02x.%u)\n", - PCI_SLOT(devfn), PCI_FUNC(devfn)); - - } else { - - GT_WRITE(GT_INTRMASK_OFS, mask & ~pending); - printk(KERN_WARNING "Galileo: masking unexpected interrupt %08x\n", pending); - } -} - static inline void via_pic_irq(struct pt_regs *regs) { int irq; @@ -79,55 +52,38 @@ static inline void via_pic_irq(struct pt asmlinkage void plat_irq_dispatch(struct pt_regs *regs) { - unsigned pending; + unsigned int pending; - pending = read_c0_status() & read_c0_cause(); + pending = read_c0_status() & read_c0_cause() & ST0_IM; if (pending & CAUSEF_IP2) /* COBALT_GALILEO_IRQ (18) */ - - galileo_irq(regs); - + gt641xx_irq_dispatch(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); + else + spurious_interrupt(regs); } -static struct irqaction irq_via = { - no_action, 0, { { 0, } }, "cascade", NULL, NULL +static struct irqaction cascade_irqaction = { + .handler = no_action, + .mask = CPU_MASK_NONE, + .name = "cascade", }; void __init arch_init_irq(void) { - /* - * Mask all Galileo interrupts. The Galileo - * handler is set in cobalt_timer_setup() - */ - GT_WRITE(GT_INTRMASK_OFS, 0); - init_i8259_irqs(); /* 0 ... 15 */ mips_cpu_irq_init(COBALT_CPU_IRQ); /* 16 ... 23 */ + gt641xx_irq_init(COBALT_GT64111_IRQ); /* 24 ... 55 */ - /* - * Mask all cpu interrupts - * (except IE4, we already masked those at VIA level) - */ - change_c0_status(ST0_IM, IE_IRQ4); - - setup_irq(COBALT_VIA_IRQ, &irq_via); + setup_irq(COBALT_GALILEO_IRQ, &cascade_irqaction); + setup_irq(COBALT_VIA_IRQ, &cascade_irqaction); } diff -pruN -X mips/Documentation/dontdiff mips-orig/arch/mips/gt64120/cobalt/setup.c mips/arch/mips/gt64120/cobalt/setup.c --- mips-orig/arch/mips/gt64120/cobalt/setup.c 2006-08-18 22:16:52.068534750 +0900 +++ mips/arch/mips/gt64120/cobalt/setup.c 2006-08-17 22:59:36.246695500 +0900 @@ -52,7 +52,7 @@ const char *get_system_type(void) void __init plat_timer_setup(struct irqaction *irq) { /* Register interrupt */ - setup_irq(COBALT_GALILEO_IRQ, irq); + setup_irq(COBALT_TIMER3_IRQ, irq); } extern struct pci_ops gt64120_pci_ops; diff -pruN -X mips/Documentation/dontdiff mips-orig/arch/mips/gt64120/common/Makefile mips/arch/mips/gt64120/common/Makefile --- mips-orig/arch/mips/gt64120/common/Makefile 2006-08-18 22:16:52.068534750 +0900 +++ mips/arch/mips/gt64120/common/Makefile 2006-08-17 22:59:36.246695500 +0900 @@ -2,4 +2,4 @@ # Makefile for common code of gt64120-based boards. # -obj-y += time.o +obj-y += irq.o time.o diff -pruN -X mips/Documentation/dontdiff mips-orig/arch/mips/gt64120/common/irq.c mips/arch/mips/gt64120/common/irq.c --- mips-orig/arch/mips/gt64120/common/irq.c 1970-01-01 09:00:00.000000000 +0900 +++ mips/arch/mips/gt64120/common/irq.c 2006-08-18 05:59:20.299939500 +0900 @@ -0,0 +1,125 @@ +/* + * Interrupt routines for Galileo GT64111/GT64120 + * + * Copyright (C) 2006 Yoichi Yuasa <yoichi_yuasa@xxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include <linux/irq.h> +#include <linux/interrupt.h> + +#include <asm/gt64120.h> + +static unsigned int gt641xx_irq_base; + +#define GT641XX_NR_IRQS 32 +#define GT641XX_IRQ_TO_BIT(irq) (1U << ((irq) - gt641xx_irq_base)) + +static unsigned int gt641xx_irq_startup(unsigned int irq) +{ + uint32_t mask; + + GT_WRITE(GT_INTRCAUSE_OFS, ~GT641XX_IRQ_TO_BIT(irq)); + + mask = GT_READ(GT_INTRMASK_OFS); + mask |= GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRMASK_OFS, mask); + + return 0; +} + +static void gt641xx_irq_shutdown(unsigned int irq) +{ + uint32_t mask; + + mask = GT_READ(GT_INTRMASK_OFS); + mask &= ~GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRMASK_OFS, mask); +} + +static void gt641xx_irq_enable(unsigned int irq) +{ + uint32_t mask; + + mask = GT_READ(GT_INTRMASK_OFS); + mask |= GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRMASK_OFS, mask); +} + +#define gt641xx_irq_disable gt641xx_irq_shutdown + +static void gt641xx_irq_ack(unsigned int irq) +{ + uint32_t mask; + + mask = GT_READ(GT_INTRMASK_OFS); + mask &= ~GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRMASK_OFS, mask); + GT_WRITE(GT_INTRCAUSE_OFS, ~GT641XX_IRQ_TO_BIT(irq)); +} + +static void gt641xx_irq_end(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) { + uint32_t mask; + + mask = GT_READ(GT_INTRMASK_OFS); + mask |= GT641XX_IRQ_TO_BIT(irq); + GT_WRITE(GT_INTRMASK_OFS, mask); + } +} + +static struct irq_chip gt641xx_irq_chip = { + .typename = "GT641xx", + .startup = gt641xx_irq_startup, + .shutdown = gt641xx_irq_shutdown, + .enable = gt641xx_irq_enable, + .disable = gt641xx_irq_disable, + .ack = gt641xx_irq_ack, + .end = gt641xx_irq_end, +}; + +void gt641xx_irq_dispatch(struct pt_regs *regs) +{ + uint32_t mask, pending; + int i; + + mask = GT_READ(GT_INTRMASK_OFS); + pending = GT_READ(GT_INTRCAUSE_OFS); + pending &= mask; + + for (i = 0; i < GT641XX_NR_IRQS; i++) { + if (pending & (1U << i)) { + do_IRQ(gt641xx_irq_base + i, regs); + break; + } + } +} + +void __init gt641xx_irq_init(unsigned int irq_base) +{ + int i; + + if (irq_base >= NR_IRQS) + return; + + gt641xx_irq_base = irq_base; + + GT_WRITE(GT_INTRMASK_OFS, 0); + GT_WRITE(GT_INTRCAUSE_OFS, 0); + + for (i = irq_base; i < irq_base + GT641XX_NR_IRQS; i++) + irq_desc[i].chip = >641xx_irq_chip; +} diff -pruN -X mips/Documentation/dontdiff mips-orig/include/asm-mips/gt64120.h mips/include/asm-mips/gt64120.h --- mips-orig/include/asm-mips/gt64120.h 2006-08-18 22:16:52.068534750 +0900 +++ mips/include/asm-mips/gt64120.h 2006-08-17 22:59:36.246695500 +0900 @@ -573,6 +573,10 @@ #define GT_READ(ofs) le32_to_cpu(__GT_READ(ofs)) #define GT_WRITE(ofs, data) __GT_WRITE(ofs, cpu_to_le32(data)) +struct pt_regs; +extern void gt641xx_irq_dispatch(struct pt_regs *regs); +extern void gt641xx_irq_init(unsigned int irq_base); + extern void gt641xx_timer3_init(void); extern void gt641xx_disable_alltimers(void); diff -pruN -X mips/Documentation/dontdiff mips-orig/include/asm-mips/mach-cobalt/cobalt.h mips/include/asm-mips/mach-cobalt/cobalt.h --- mips-orig/include/asm-mips/mach-cobalt/cobalt.h 2006-08-18 22:16:52.068534750 +0900 +++ mips/include/asm-mips/mach-cobalt/cobalt.h 2006-08-17 22:59:36.262696500 +0900 @@ -16,18 +16,18 @@ * i8259 legacy interrupts used on Cobalt: * * 8 - RTC - * 9 - PCI + * 9 - PCI slot * 14 - IDE0 * 15 - IDE1 */ #define COBALT_QUBE_SLOT_IRQ 9 /* - * CPU IRQs are 16 ... 23 + * CPU IRQs are 16 ... 23 */ #define COBALT_CPU_IRQ 16 -#define COBALT_GALILEO_IRQ (COBALT_CPU_IRQ + 2) +#define COBALT_GALILEO_IRQ (COBALT_CPU_IRQ + 2) /* Chained to Galileo GT64111 */ #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) @@ -38,6 +38,13 @@ #define COBALT_VIA_IRQ (COBALT_CPU_IRQ + 6) /* Chained to VIA ISA bridge */ /* + * GT64111 IRQs are 24 ... 55 + */ +#define COBALT_GT64111_IRQ 24 + +#define COBALT_TIMER3_IRQ (COBALT_GT64111_IRQ + 11) + +/* * PCI configuration space manifest constants. These are wired into * the board layout according to the PCI spec to enable the software * to probe the hardware configuration space in a well defined manner.