From: Jim P. <jim...@us...> - 2001-11-26 01:39:00
|
Update of /cvsroot/linux-mips/linux/arch/mips/vr4111/common In directory usw-pr-cvs1:/tmp/cvs-serv24952 Modified Files: icu.c int-handler.S irq.c Log Message: General cleanup, various fixups for IRQ code. Index: icu.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/vr4111/common/icu.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- icu.c 2001/10/28 23:04:19 1.1 +++ icu.c 2001/11/26 01:38:57 1.2 @@ -13,20 +13,6 @@ * 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/config.h> #include <asm/io.h> @@ -40,7 +26,7 @@ * binary search to find which actual IRQ occurred. */ -asmlinkage void int0_icu_irqdispatch(struct pt_regs *regs) +asmlinkage int icu_handle_int(struct pt_regs *regs) { u16 pend1, pend2; int irq; @@ -50,8 +36,8 @@ pend2 = *VR41XX_SYSINT2REG & *VR41XX_MSYSINT2REG; if (pend1) { + /* If highest priority interrupt is a GIU cascade, handle it */ if ((pend1 & 0x01ff) == 0x0100) { - /* Handle the GIU interrupt */ pend1 = *VR41XX_GIUINTLREG & *VR41XX_MGIUINTLREG; pend2 = *VR41XX_GIUINTHREG & *VR41XX_MGIUINTHREG; if (pend1) { @@ -63,7 +49,7 @@ search = pend2; /* ... fall through to search */ } else { - return; + return 0; } } else { @@ -77,29 +63,33 @@ search = pend2; /* ... fall through to search */ } else { - return; + return 0; } - if(search & 0xFF00) { + /* Search for interrupts, giving priority to bits towards the LSB */ + + if(!(search & 0x00FF)) { search >>= 8; irq += 8; } - if(search & 0xF0) { + if(!(search & 0x0F)) { search >>= 4; irq += 4; } - if(search & 0xC) { + if(!(search & 0x3)) { search >>= 2; irq += 2; } - if(search & 2) { + if(!(search & 1)) { irq += 1; } do_IRQ(irq, regs); + + return 1; } Index: int-handler.S =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/vr4111/common/int-handler.S,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- int-handler.S 2001/10/28 23:04:19 1.1 +++ int-handler.S 2001/11/26 01:38:57 1.2 @@ -1,112 +1,76 @@ /* - * BRIEF MODULE DESCRIPTION - * Interrupt dispatcher for NEC Vr4111 CPU core. - * - * Copyright 2001 MontaVista Software Inc. - * Author Yoichi Yuasa - * yy...@mv... or so...@mv... - * - * Adapted for VR4111 from arch/mips/vr4122/common/int-handler.S - * by Jim Paris <ji...@jt...> - * - * 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. + * VR4111 interrupt dispatcher for CPU core interrupts + * Copyright (c) 2001 Jim Paris <ji...@jt...> * - * 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. + * 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. */ #include <linux/config.h> + #include <asm/asm.h> -#include <asm/regdef.h> #include <asm/mipsregs.h> +#include <asm/addrspace.h> +#include <asm/regdef.h> #include <asm/stackframe.h> - #include <asm/vr41xx.h> - - .text - .set noreorder - .align 5 - NESTED(vr4111_handle_int, PT_SIZE, ra) - .set noat + .align 5 + NESTED(vr4111_handle_int, PT_SIZE, sp) SAVE_ALL CLI .set at .set noreorder - - /* Get a list of pending interrupts that are not disabled */ + + nop # possible CP0 hazard from a mtc0 in CLI mfc0 t0, CP0_CAUSE - mfc0 t1, CP0_STATUS - and t0, t0, t1 - - andi t1, t0, CAUSEF_IP7 # timer interrupt - beqz t1, 1f - li a0, 7 - jal ll_timer_interrupt - move a1, sp - j ret_from_irq + mfc0 t2, CP0_STATUS + and t0, t2 -1: - andi t1, t0, 0x7800 # check for IP3-6 - beqz t1, 2f +#define check_ip(x) \ + andi t1, t0, CAUSEF_IP##x; \ + bnez t1, handle_ip##x - andi t1, t0, CAUSEF_IP3 # check for IP3 (rtc_long1) - bnez t1, handle_it - li a0, 3 + check_ip(7) # timer interrupt + check_ip(3) # RTC interrupt 1 + check_ip(4) # RTC interrupt 2 + check_ip(5) # HSP modem interrupt + check_ip(2) # cascade to ICU + check_ip(0) # software interrupt 0 + check_ip(1) # software interrupt 1 +#undef check_ip - andi t1, t0, CAUSEF_IP4 # check for IP4 (rtc_long2) - bnez t1, handle_it - li a0, 4 + .set reorder + j spurious_interrupt + nop + END(vr4111_handle_int) - andi t1, t0, CAUSEF_IP5 # check for IP5 (hsp) - bnez t1, handle_it - li a0, 5 + .align 5 + +/* Build an appropriate label and code to handle non-cascaded interrupts */ +#define handle_ip(x) \ +handle_ip##x: \ + li a0, x; \ + move a1, sp; \ + jal do_IRQ; \ + j ret_from_irq -/* Int4 will never occur on the VR4111 (user manual, 7.3.6) - * andi t1, t0, CAUSEF_IP6 # check for IP6 (Int4) - * bnez t1, handle_it - * li a0, 6 - */ + handle_ip(7) + handle_ip(3) + handle_ip(4) + handle_ip(5) + handle_ip(0) + handle_ip(1) +#undef handle_ip -2: - andi t1, t0, CAUSEF_IP2 # check for IP2 (all other interrupts) - beqz t1, 3f +/* This is the special handler for the cascaded interrupt */ +handle_ip2: move a0, sp - jal int0_icu_irqdispatch # in C for implementation ease - nop + jal icu_handle_int + beqz v0, icu_spurious j ret_from_irq - nop - -3: - andi t1, t0, CAUSEF_IP0 # check for IP0 (software 0) - bnez t1, handle_it - li a0, 0 - andi t1, t0, CAUSEF_IP1 # check for IP1 (software 1) - bnez t1, handle_it - li a0, 1 - +icu_spurious: j spurious_interrupt - nop - -handle_it: - jal do_IRQ - move a1, sp - j ret_from_irq - - END(vr4111_handle_int) Index: irq.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/vr4111/common/irq.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- irq.c 2001/10/28 23:04:19 1.1 +++ irq.c 2001/11/26 01:38:57 1.2 @@ -23,6 +23,7 @@ #include <linux/malloc.h> #include <linux/random.h> +#include <asm/system.h> #include <asm/irq.h> #include <asm/mipsregs.h> #include <asm/gdb-stub.h> @@ -47,30 +48,25 @@ static void sys_irq_enable(unsigned int irq) { - if(irq==VR41XX_IRQ_DSIU) - *VR41XX_MDSIUINTREG |= 0x0800; irq -= sys_irq_base; if (irq < 16) { - *VR41XX_MSYSINT1REG |= (u16)(1 << irq); + *VR41XX_MSYSINT1REG |= (u16)1 << irq; } else { irq -= 16; - *VR41XX_MSYSINT2REG |= (u16)(1 << irq); + *VR41XX_MSYSINT2REG |= (u16)1 << irq; } } static void sys_irq_disable(unsigned int irq) { - if(irq==VR41XX_IRQ_DSIU) - *VR41XX_MDSIUINTREG = 0; irq -= sys_irq_base; if (irq < 16) { - *VR41XX_MSYSINT1REG &= ~((u16)(1 << irq)); + *VR41XX_MSYSINT1REG &= ~((u16)1 << irq); } else { irq -= 16; - *VR41XX_MSYSINT2REG &= ~((u16)(1 << irq)); + *VR41XX_MSYSINT2REG &= ~((u16)1 << irq); } - } static unsigned int @@ -82,7 +78,13 @@ #define sys_irq_shutdown sys_irq_disable #define sys_irq_ack sys_irq_disable -#define sys_irq_end sys_irq_enable + +static void +sys_irq_end(unsigned int irq) +{ + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + sys_irq_enable(irq); +} static hw_irq_controller sys_irq_controller = { "vr4111_sys_irq", @@ -99,15 +101,14 @@ static void gpio_irq_clear(unsigned int irq) { - /* clear interrupt if edge triggered; write a 1 to clear */ irq -= gpio_irq_base; if (irq < 16) { - if(*VR41XX_GIUINTTYPL & ((u16)1 << irq)) - *VR41XX_GIUINTSTATL = ((u16)1 << irq); + if(*VR41XX_GIUINTHTSELL & ((u16)1 << irq)) + *VR41XX_GIUINTSTATL = (u16)1 << irq; } else { irq -= 16; - if(*VR41XX_GIUINTTYPH & ((u16)1 << irq)) - *VR41XX_GIUINTSTATH = ((u16)1 << irq); + if(*VR41XX_GIUINTHTSELH & ((u16)1 << irq)) + *VR41XX_GIUINTSTATH = (u16)1 << irq; } } @@ -115,13 +116,12 @@ gpio_irq_enable(unsigned int irq) { gpio_irq_clear(irq); - irq -= gpio_irq_base; if (irq < 16) { - *VR41XX_MGIUINTLREG |= (u16)(1 << irq); + *VR41XX_MGIUINTLREG |= (u16)1 << irq; } else { irq -= 16; - *VR41XX_MGIUINTHREG |= (u16)(1 << irq); + *VR41XX_MGIUINTHREG |= (u16)1 << irq; } } @@ -130,10 +130,10 @@ { irq -= gpio_irq_base; if (irq < 16) { - *VR41XX_MGIUINTLREG &= ~((u16)(1 << irq)); + *VR41XX_MGIUINTLREG &= ~((u16)1 << irq); } else { irq -= 16; - *VR41XX_MGIUINTHREG &= ~((u16)(1 << irq)); + *VR41XX_MGIUINTHREG &= ~((u16)1 << irq); } } @@ -141,31 +141,10 @@ gpio_irq_startup(unsigned int irq) { gpio_irq_enable(irq); - - irq -= gpio_irq_base; - if (irq < 16) { - *VR41XX_GIUINTENL |= (u16)(1 << irq); - } else { - irq -= 16; - *VR41XX_GIUINTENH |= (u16)(1 << irq); - } - return 0; } -static void -gpio_irq_shutdown(unsigned int irq) -{ - gpio_irq_disable(irq); - - irq -= gpio_irq_base; - if (irq < 16) { - *VR41XX_GIUINTENL &= ~((u16)(1 << irq)); - } else { - irq -= 16; - *VR41XX_GIUINTENH &= ~((u16)(1 << irq)); - } -} +#define gpio_irq_shutdown gpio_irq_disable static void gpio_irq_ack(unsigned int irq) @@ -174,7 +153,12 @@ gpio_irq_clear(irq); } -#define gpio_irq_end gpio_irq_enable +static void +gpio_irq_end(unsigned int irq) +{ + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + gpio_irq_enable(irq); +} static hw_irq_controller gpio_irq_controller = { "vr4111_gpio_irq", @@ -190,20 +174,26 @@ /* --------------------- IRQ init stuff ---------------------- */ extern asmlinkage void vr4111_handle_int(void); +extern void init_generic_irq(void); extern void breakpoint(void); extern int setup_irq(unsigned int irq, struct irqaction *irqaction); extern void mips_cpu_irq_init(u32 irq_base); static struct irqaction cascade = { no_action, SA_INTERRUPT, 0, "cascade", NULL, NULL }; -static struct irqaction reserved = - { no_action, SA_INTERRUPT, 0, "reserved", NULL, NULL }; void __init init_IRQ(void) { int i; extern irq_desc_t irq_desc[]; +#if (NR_IRQS < (VR41XX_SYS_IRQ_BASE + VR41XX_NUM_SYS_IRQ)) +#error -- NR_IRQS (in include/asm/irq.h) is too low for SYS IRQs! +#endif +#if (NR_IRQS < (VR41XX_GPIO_IRQ_BASE + VR41XX_NUM_GPIO_IRQ)) +#error -- NR_IRQS (in include/asm/irq.h) is too low for GPIO IRQs! +#endif + init_generic_irq(); mips_cpu_irq_init(VR41XX_CPU_IRQ_BASE); @@ -228,8 +218,15 @@ /* Default all ICU IRQs to off ... */ *VR41XX_MSYSINT1REG = 0; *VR41XX_MSYSINT2REG = 0; + + /* Make sure the RTC unit is disabled; clear RTC interrupts */ + *VR41XX_RTCL1LREG = 0; + *VR41XX_RTCL1HREG = 0; + *VR41XX_RTCL2LREG = 0; + *VR41XX_RTCL2HREG = 0; + *VR41XX_RTCINTREG = 6; /* 0110b */ - /* We initialize the level 2 ICU registers to all bits disabled. */ + /* Disable all level 2 ICU interrupts */ *VR41XX_MPIUINTREG = 0; *VR41XX_MAIUINTREG = 0; *VR41XX_MKIUINTREG = 0; @@ -238,16 +235,16 @@ *VR41XX_MGIUINTLREG = 0; *VR41XX_MGIUINTHREG = 0; - /* Disable and clear all GPIO interrupts */ - *VR41XX_GIUINTENL = 0; - *VR41XX_GIUINTENH = 0; + /* Only allow GPIO interrupts on lines configured as input */ + *VR41XX_GIUINTENL = ~*VR41XX_GIUIOSELL; + *VR41XX_GIUINTENH = ~*VR41XX_GIUIOSELH; + + /* Clear all GPIO interrupts */ *VR41XX_GIUINTSTATL = 0xffff; *VR41XX_GIUINTSTATH = 0xffff; setup_irq(VR41XX_IRQ_INT0, &cascade); setup_irq(VR41XX_IRQ_GIU, &cascade); - setup_irq(VR41XX_IRQ_RTCL1, &reserved); - setup_irq(VR41XX_IRQ_RTCL2, &reserved); set_except_vector(0, vr4111_handle_int); |