diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/config.in | 3 | ||||
-rw-r--r-- | arch/mips/defconfig | 2 | ||||
-rw-r--r-- | arch/mips/defconfig-ip22 | 2 | ||||
-rw-r--r-- | arch/mips/defconfig-ocelot | 1 | ||||
-rw-r--r-- | arch/mips/gt64120/common/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/gt64120/common/gt_irq.c | 7 | ||||
-rw-r--r-- | arch/mips/gt64120/common/irq.c | 300 | ||||
-rw-r--r-- | arch/mips/gt64120/momenco_ocelot/int-handler.S | 43 | ||||
-rw-r--r-- | arch/mips/gt64120/momenco_ocelot/irq.c | 150 | ||||
-rw-r--r-- | arch/mips/gt64120/momenco_ocelot/pci.c | 6 | ||||
-rw-r--r-- | arch/mips/gt64120/momenco_ocelot/setup.c | 2 |
11 files changed, 138 insertions, 380 deletions
diff --git a/arch/mips/config.in b/arch/mips/config.in index e9a077e3b..5d5c66207 100644 --- a/arch/mips/config.in +++ b/arch/mips/config.in @@ -135,6 +135,7 @@ if [ "$CONFIG_MOMENCO_OCELOT" = "y" ]; then define_bool CONFIG_PCI y define_bool CONFIG_SYSCLK_100 y define_bool CONFIG_SWAP_IO_SPACE y + define_bool CONFIG_NEW_IRQ y define_bool CONFIG_OLD_TIME_C y fi if [ "$CONFIG_SGI_IP22" = "y" ]; then @@ -142,8 +143,8 @@ if [ "$CONFIG_SGI_IP22" = "y" ]; then define_bool CONFIG_BOARD_SCACHE y define_bool CONFIG_PC_KEYB y define_bool CONFIG_SGI y - define_bool CONFIG_OLD_TIME_C y define_bool CONFIG_NEW_IRQ y + define_bool CONFIG_OLD_TIME_C y fi if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then define_bool CONFIG_ARC32 y diff --git a/arch/mips/defconfig b/arch/mips/defconfig index 6d63c50ae..07d92fff4 100644 --- a/arch/mips/defconfig +++ b/arch/mips/defconfig @@ -38,8 +38,8 @@ CONFIG_ARC32=y CONFIG_BOARD_SCACHE=y CONFIG_PC_KEYB=y CONFIG_SGI=y -CONFIG_OLD_TIME_C=y CONFIG_NEW_IRQ=y +CONFIG_OLD_TIME_C=y # CONFIG_ISA is not set # CONFIG_EISA is not set # CONFIG_PCI is not set diff --git a/arch/mips/defconfig-ip22 b/arch/mips/defconfig-ip22 index 6d63c50ae..07d92fff4 100644 --- a/arch/mips/defconfig-ip22 +++ b/arch/mips/defconfig-ip22 @@ -38,8 +38,8 @@ CONFIG_ARC32=y CONFIG_BOARD_SCACHE=y CONFIG_PC_KEYB=y CONFIG_SGI=y -CONFIG_OLD_TIME_C=y CONFIG_NEW_IRQ=y +CONFIG_OLD_TIME_C=y # CONFIG_ISA is not set # CONFIG_EISA is not set # CONFIG_PCI is not set diff --git a/arch/mips/defconfig-ocelot b/arch/mips/defconfig-ocelot index e0626c3e0..1a273d09c 100644 --- a/arch/mips/defconfig-ocelot +++ b/arch/mips/defconfig-ocelot @@ -37,6 +37,7 @@ CONFIG_MOMENCO_OCELOT=y CONFIG_PCI=y CONFIG_SYSCLK_100=y CONFIG_SWAP_IO_SPACE=y +CONFIG_NEW_IRQ=y CONFIG_OLD_TIME_C=y # CONFIG_ISA is not set # CONFIG_EISA is not set diff --git a/arch/mips/gt64120/common/Makefile b/arch/mips/gt64120/common/Makefile index ccf50a55b..e1c4e42a0 100644 --- a/arch/mips/gt64120/common/Makefile +++ b/arch/mips/gt64120/common/Makefile @@ -13,6 +13,6 @@ O_TARGET:= gt64120.o -obj-y := gt_irq.o irq.o pci.o +obj-y := gt_irq.o pci.o include $(TOPDIR)/Rules.make diff --git a/arch/mips/gt64120/common/gt_irq.c b/arch/mips/gt64120/common/gt_irq.c index afd91e4ba..caefccbfd 100644 --- a/arch/mips/gt64120/common/gt_irq.c +++ b/arch/mips/gt64120/common/gt_irq.c @@ -1,4 +1,4 @@ -/*********************************************************************** +/* * * Copyright 2001 MontaVista Software Inc. * Author: jsun@mvista.com or jsun@junsun.net @@ -10,10 +10,7 @@ * 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. - * - *********************************************************************** */ - #include <linux/module.h> #include <linux/interrupt.h> #include <linux/kernel.h> @@ -198,7 +195,7 @@ static void gt64120_irq(int irq, void *dev_id, struct pt_regs *regs) * that is passed in as *irq (=irq0 in ../kernel/time.c). * We will do our own timer interrupt handling. */ -void gt64120_time_init(struct irqaction *irq) +void gt64120_time_init(void) { extern irq_desc_t irq_desc[NR_IRQS]; static struct irqaction timer; diff --git a/arch/mips/gt64120/common/irq.c b/arch/mips/gt64120/common/irq.c deleted file mode 100644 index 8fc47ede0..000000000 --- a/arch/mips/gt64120/common/irq.c +++ /dev/null @@ -1,300 +0,0 @@ -/* - * arch/mips/gt64120/common/irq.c - * Top-level irq code. This is really common among all MIPS boards. - * Should be "upgraded" to arch/mips/kernel/irq.c - * - * Copyright (C) 2000 RidgeRun, Inc. - * Author: RidgeRun, Inc. - * glonnon@ridgerun.com, skranz@ridgerun.com, stevej@ridgerun.com - * - * Copyright 2001 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * 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., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/kernel_stat.h> -#include <linux/module.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/timex.h> -#include <linux/slab.h> -#include <linux/random.h> -#include <linux/irq.h> -#include <asm/bitops.h> -#include <asm/bootinfo.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/mipsregs.h> -#include <asm/system.h> -#include <asm/pmc/ev64120int.h> - - -#undef IRQ_DEBUG - -#ifdef IRQ_DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -void (*irq_setup)(void); - -/* - * Generic no controller code - */ - -static void no_irq_enable_disable(unsigned int irq) -{ -} - -static unsigned int no_irq_startup(unsigned int irq) -{ - return 0; -} - -static void no_irq_ack(unsigned int irq) -{ - printk(KERN_CRIT "Unexpected IRQ trap at vector %u\n", irq); -} - -struct hw_interrupt_type no_irq_type = { - typename: "none", - startup: no_irq_startup, - shutdown: no_irq_enable_disable, - enable: no_irq_enable_disable, - disable: no_irq_enable_disable, - // ack: no_irq_ack, - // [jsun] cannot use it yet. gt64120 does not have its own handler - ack: NULL, - end: no_irq_enable_disable, -}; - - - -/* - * Controller mappings for all interrupt sources: - */ -irq_desc_t irq_desc[NR_IRQS]; - -unsigned long spurious_count = 0; - -int get_irq_list(char *buf) -{ - int i, len = 0, j; - struct irqaction *action; - - len += sprintf(buf + len, " "); - for (j = 0; j < smp_num_cpus; j++) - len += sprintf(buf + len, "CPU%d ", j); - *(char *) (buf + len++) = '\n'; - - for (i = 0; i < NR_IRQS; i++) { - action = irq_desc[i].action; - if (!action || !action->handler) - continue; - len += sprintf(buf + len, "%3d: ", i); - len += sprintf(buf + len, "%10u ", kstat_irqs(i)); - if (irq_desc[i].handler) - len += - sprintf(buf + len, " %s ", - irq_desc[i].handler->typename); - else - len += sprintf(buf + len, " None "); - len += sprintf(buf + len, " %s", action->name); - for (action = action->next; action; action = action->next) { - len += sprintf(buf + len, ", %s", action->name); - } - len += sprintf(buf + len, "\n"); - } - len += sprintf(buf + len, "BAD: %10lu\n", spurious_count); - return len; -} - -asmlinkage void do_IRQ(int irq, struct pt_regs *regs) -{ - struct irqaction *action; - int cpu; - cpu = smp_processor_id(); - irq_enter(cpu, irq); - kstat.irqs[cpu][irq]++; - if (irq_desc[irq].handler->ack) { - irq_desc[irq].handler->ack(irq); - } - - disable_irq(irq); - - action = irq_desc[irq].action; - if (action && action->handler) { -#ifdef IRQ_DEBUG - if (irq != TIMER) - DBG(KERN_INFO - "rr: irq %d action %p and handler %p\n", irq, - action, action->handler); -#endif - if (!(action->flags & SA_INTERRUPT)) - __sti(); - do { - action->handler(irq, action->dev_id, regs); - action = action->next; - } while (action); - __cli(); - if (irq_desc[irq].handler) { - if (irq_desc[irq].handler->end) - irq_desc[irq].handler->end(irq); - else if (irq_desc[irq].handler->enable) - irq_desc[irq].handler->enable(irq); - } - } - - enable_irq(irq); - irq_exit(cpu, irq); - - if (softirq_active(cpu) & softirq_mask(cpu)) - do_softirq(); - - /* unmasking and bottom half handling is done magically for us. */ -} - -int request_irq(unsigned int irq, - void (*handler) (int, void *, struct pt_regs *), - unsigned long irqflags, const char *devname, void *dev_id) -{ - struct irqaction *old, **p, *action; - unsigned long flags; - if (irq >= NR_IRQS) - return -EINVAL; - - action = (struct irqaction *) - kmalloc(sizeof(struct irqaction), GFP_KERNEL); - if (!action) - return -ENOMEM; - - action->handler = handler; - action->flags = irqflags; - action->mask = 0; - action->name = devname; - action->dev_id = dev_id; - action->next = NULL; - - save_flags(flags); - cli(); - - p = &irq_desc[irq].action; - - if ((old = *p) != NULL) { - /* Can't share interrupts unless both agree to */ - if (!(old->flags & action->flags & SA_SHIRQ)) - return -EBUSY; - /* add new interrupt at end of irq queue */ - do { - p = &old->next; - old = *p; - } while (old); - } - *p = action; - - restore_flags(flags); - enable_irq(irq); - - return 0; -} - - -void free_irq(unsigned int irq, void *dev_id) -{ - struct irqaction *p, *old = NULL; - unsigned long flags; - int count, tmp, removed = 0; - - for (p = irq_desc[irq].action; p != NULL; old = p, p = p->next) { - /* Found the IRQ, is it the correct dev_id? */ - if (dev_id == p->dev_id) { - save_flags(flags); - cli(); - - // remove link from list - if (old) - old->next = p->next; - else - irq_desc[irq].action = p->next; - - restore_flags(flags); - kfree(p); - removed = 1; - break; - } - } -} - -unsigned long probe_irq_on(void) -{ - printk(KERN_INFO "probe_irq_on\n"); - return 0; -} - -int probe_irq_off(unsigned long irqs) -{ - printk(KERN_INFO "probe_irq_off\n"); - return 0; -} - -void __init init_IRQ(void) -{ - int i; - - DBG(KERN_INFO "rr:init_IRQ\n"); - - /* Let's initialize our IRQ descriptors */ - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].status = 0; - irq_desc[i].handler = &no_irq_type; - irq_desc[i].action = NULL; - irq_desc[i].depth = 0; - irq_desc[i].lock = SPIN_LOCK_UNLOCKED; - } - - irq_setup(); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/arch/mips/gt64120/momenco_ocelot/int-handler.S b/arch/mips/gt64120/momenco_ocelot/int-handler.S index df0525833..4d8f82d54 100644 --- a/arch/mips/gt64120/momenco_ocelot/int-handler.S +++ b/arch/mips/gt64120/momenco_ocelot/int-handler.S @@ -43,6 +43,26 @@ bnez t1, ll_galileo_irq andi t1, t0, STATUSF_IP7 /* cpu timer */ bnez t1, ll_cputimer_irq + + /* now look at the extended interrupts */ + mfc0 t0, CP0_CAUSE + cfc0 t1, CP0_S1_INTCONTROL + + /* shift the mask 8 bits left to line up the bits */ + sll t2, t1, 8 + + and t0, t2 + srl t0, t0, 16 + + andi t1, t0, STATUSF_IP8 /* int6 hardware line */ + bnez t1, ll_pmc1_irq + andi t1, t0, STATUSF_IP9 /* int7 hardware line */ + bnez t1, ll_pmc2_irq + andi t1, t0, STATUSF_IP10 /* int8 hardware line */ + bnez t1, ll_cpci_abcd_irq + andi t1, t0, STATUSF_IP11 /* int9 hardware line */ + bnez t1, ll_uart2_irq + .set reorder /* wrong alarm or masked ... */ @@ -87,3 +107,26 @@ ll_cputimer_irq: jal do_IRQ j ret_from_irq +ll_pmc1_irq: + li a0, 8 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_pmc2_irq: + li a0, 9 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_cpci_abcd_irq: + li a0, 10 + move a1, sp + jal do_IRQ + j ret_from_irq + +ll_uart2_irq: + li a0, 11 + move a1, sp + jal do_IRQ + j ret_from_irq diff --git a/arch/mips/gt64120/momenco_ocelot/irq.c b/arch/mips/gt64120/momenco_ocelot/irq.c index c6c01b0d3..e28be4037 100644 --- a/arch/mips/gt64120/momenco_ocelot/irq.c +++ b/arch/mips/gt64120/momenco_ocelot/irq.c @@ -5,6 +5,7 @@ * * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org) * * 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 @@ -48,116 +49,125 @@ #include <asm/system.h> -#undef IRQ_DEBUG - -#ifdef IRQ_DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - +static spinlock_t rm7000_irq_lock = SPIN_LOCK_UNLOCKED; /* Function for careful CP0 interrupt mask access */ -static inline void modify_cp0_intmask(unsigned clr_mask, unsigned set_mask) +static inline void modify_cp0_intmask(unsigned clr_mask_in, unsigned set_mask_in) { - unsigned long status = read_32bit_cp0_register(CP0_STATUS); - DBG(KERN_INFO "modify_cp0_intmask clr %x, set %x\n", clr_mask, - set_mask); - DBG(KERN_INFO "modify_cp0_intmask status %x\n", status); + unsigned long status; + unsigned clr_mask; + unsigned set_mask; + + /* do the low 8 bits first */ + clr_mask = 0xff & clr_mask_in; + set_mask = 0xff & set_mask_in; + status = read_32bit_cp0_register(CP0_STATUS); status &= ~((clr_mask & 0xFF) << 8); status |= (set_mask & 0xFF) << 8; - DBG(KERN_INFO "modify_cp0_intmask status %x\n", status); write_32bit_cp0_register(CP0_STATUS, status); + + /* do the high 8 bits */ + clr_mask = 0xff & (clr_mask_in >> 8); + set_mask = 0xff & (set_mask_in >> 8); + status = read_32bit_cp0_set1_register(CP0_S1_INTCONTROL); + status &= ~((clr_mask & 0xFF) << 8); + status |= (set_mask & 0xFF) << 8; + write_32bit_cp0_set1_register(CP0_S1_INTCONTROL, status); } -static inline void mask_irq(unsigned int irq_nr) +static inline void mask_irq(unsigned int irq) { - modify_cp0_intmask(irq_nr, 0); + modify_cp0_intmask(irq, 0); } -static inline void unmask_irq(unsigned int irq_nr) +static inline void unmask_irq(unsigned int irq) { - modify_cp0_intmask(0, irq_nr); + modify_cp0_intmask(0, irq); } -void disable_irq(unsigned int irq_nr) +static void enable_cp7000_irq(unsigned int irq) { unsigned long flags; - DBG(KERN_INFO "disable_irq, irq %d\n", irq_nr); - save_and_cli(flags); - /* we don't support higher interrupts, nor cascaded interrupts */ - if (irq_nr >= 8) - panic("irq_nr is greater than 8"); - - mask_irq(1 << irq_nr); - restore_flags(flags); + spin_lock_irqsave(&rm7000_irq_lock, flags); + unmask_irq(1 << irq); + spin_unlock_irqrestore(&rm7000_irq_lock, flags); +} + +static unsigned int startup_cp7000_irq(unsigned int irq) +{ + enable_cp7000_irq(irq); + + return 0; /* never anything pending */ } -void enable_irq(unsigned int irq_nr) +static void disable_cp7000_irq(unsigned int irq) { unsigned long flags; - save_and_cli(flags); - - if ( irq_nr >= 8 ) - panic("irq_nr is greater than 8"); - - unmask_irq( 1 << irq_nr ); - restore_flags(flags); + spin_lock_irqsave(&rm7000_irq_lock, flags); + mask_irq(1 << irq); + spin_unlock_irqrestore(&rm7000_irq_lock, flags); } -/* - * Ocelot irq setup - - * - * Initializes CPU interrupts - * - * - * Inputs : - * - * Outpus : - * - */ -void momenco_ocelot_irq_setup(void) +#define shutdown_cp7000_irq disable_cp7000_irq + +static void mask_and_ack_cp7000_irq(unsigned int irq) +{ + mask_irq(1 << irq); +} + +static void end_cp7000_irq(unsigned int irq) { - extern asmlinkage void ocelot_handle_int(void); - extern void gt64120_irq_init(void); + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + unmask_irq(1 << irq); +} - DBG(KERN_INFO "rr: momenco_ocelot_irq_setup entry\n"); +static struct hw_interrupt_type cp7000_hpcdma_irq_type = { + "CP7000", + startup_cp7000_irq, + shutdown_cp7000_irq, + enable_cp7000_irq, + disable_cp7000_irq, + mask_and_ack_cp7000_irq, + end_cp7000_irq, + NULL +}; - gt64120_irq_init(); + +extern asmlinkage void ocelot_handle_int(void); +extern void gt64120_irq_init(void); + +void __init init_IRQ(void) +{ + int i; /* * Clear all of the interrupts while we change the able around a bit. * int-handler is not on bootstrap */ clear_cp0_status(ST0_IM | ST0_BEV); + __cli(); /* Sets the first-level interrupt dispatcher. */ set_except_vector(0, ocelot_handle_int); + init_generic_irq(); - cli(); - - /* - * Enable timer. Other interrupts will be enabled as they are - * registered. - */ - // change_cp0_status(ST0_IM, IE_IRQ4); + for (i = 0; i <= 15; i++) { + irq_desc[i].status = IRQ_DISABLED; + irq_desc[i].action = 0; + irq_desc[i].depth = 1; + irq_desc[i].handler = &cp7000_hpcdma_irq_type; + } + gt64120_irq_init(); #ifdef CONFIG_REMOTE_DEBUG - { - /* - extern int DEBUG_CHANNEL; - serial_init(DEBUG_CHANNEL); - serial_set(DEBUG_CHANNEL, 115200); - */ - printk("start kgdb ...\n"); - set_debug_traps(); - breakpoint(); /* you may move this line to whereever you want :-) */ -#ifdef CONFIG_GDB_CONSOLE - register_gdb_console(); + printk("start kgdb ...\n"); + set_debug_traps(); + breakpoint(); /* you may move this line to whereever you want :-) */ #endif - } +#ifdef CONFIG_GDB_CONSOLE + register_gdb_console(); #endif } diff --git a/arch/mips/gt64120/momenco_ocelot/pci.c b/arch/mips/gt64120/momenco_ocelot/pci.c index 04727f885..4b8e41b2b 100644 --- a/arch/mips/gt64120/momenco_ocelot/pci.c +++ b/arch/mips/gt64120/momenco_ocelot/pci.c @@ -53,6 +53,12 @@ void __init gt64120_board_pcibios_fixup_bus(struct pci_bus *bus) "found unexpected PCI device in slot 2."); } devices->irq = 3; /* irq_nr is 3 for INT1 */ + } else if (PCI_SLOT(devices->devfn) == 4) { + /* PMC Slot 1 */ + devices->irq = 8; /* irq_nr is 8 for INT6 */ + } else if (PCI_SLOT(devices->devfn) == 5) { + /* PMC Slot 1 */ + devices->irq = 9; /* irq_nr is 9 for INT7 */ } else { /* We don't have assign interrupts for other devices. */ devices->irq = 0xff; diff --git a/arch/mips/gt64120/momenco_ocelot/setup.c b/arch/mips/gt64120/momenco_ocelot/setup.c index f08f32074..4bfc71b8f 100644 --- a/arch/mips/gt64120/momenco_ocelot/setup.c +++ b/arch/mips/gt64120/momenco_ocelot/setup.c @@ -88,7 +88,7 @@ void __init momenco_ocelot_setup(void) { void (*l3func)(unsigned long)=KSEG1ADDR(&setup_l3cache); unsigned int tmpword; - irq_setup = momenco_ocelot_irq_setup; + board_time_init = gt64120_time_init; _machine_restart = momenco_ocelot_restart; |