From: Paul M. <le...@us...> - 2002-07-12 20:14:30
|
Update of /cvsroot/linux-mips/linux/arch/mips/vr41xx/common In directory usw-pr-cvs1:/tmp/cvs-serv32248/arch/mips/vr41xx/common Modified Files: Makefile time.c Added Files: bcu.c cmu.c giu.c icu.c serial.c Removed Files: irq.c Log Message: Merge yoichi-san's vr41xx patch. Still some cleanups needed.. --- NEW FILE: bcu.c --- /* * FILE NAME * arch/mips/vr41xx/common/bcu.c * * BRIEF MODULE DESCRIPTION * Bus Control Unit routines for the NEC VR4100 series. * * Author: Yoichi Yuasa * yy...@mv... or so...@mv... * * Copyright 2002 MontaVista Software Inc. * * 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. */ /* * Changes: * MontaVista Software Inc. <yy...@mv...> or <so...@mv...> * - Added support for NEC VR4111 and VR4121. * * Paul Mundt <le...@ch...> * - Calculate mips_counter_frequency properly on VR4131. * * MontaVista Software Inc. <yy...@mv...> or <so...@mv...> * - New creation, NEC VR4122 and VR4131 are supported. */ #include <linux/init.h> #include <linux/types.h> #include <asm/addrspace.h> #include <asm/cpu.h> #include <asm/io.h> #include <asm/time.h> #define VR4111_CLKSPEEDREG KSEG1ADDR(0x0b000014) #define VR4122_CLKSPEEDREG KSEG1ADDR(0x0f000014) #define VR4131_CLKSPEEDREG VR4122_CLKSPEEDREG #define CLKSP(x) ((x) & 0x001f) #define DIV2B 0x8000 #define DIV3B 0x4000 #define DIV4B 0x2000 #define DIVT(x) (((x) & 0xf000) >> 12) #define DIVVT(x) (((x) & 0x0f00) >> 8) #define TDIVMODE(x) (2 << (((x) & 0x1000) >> 12)) #define VTDIVMODE(x) (((x) & 0x0700) >> 8) unsigned long vr41xx_vtclock = 0; static inline u16 read_clkspeed(void) { switch (mips_cpu.cputype) { case CPU_VR4111: case CPU_VR4121: return readw(VR4111_CLKSPEEDREG); case CPU_VR4122: return readw(VR4122_CLKSPEEDREG); case CPU_VR4131: return readw(VR4131_CLKSPEEDREG); default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } return 0; } static inline unsigned long calculate_pclock(u16 clkspeed) { unsigned long pclock = 0; switch (mips_cpu.cputype) { case CPU_VR4111: case CPU_VR4121: pclock = 18432000 * 64; break; case CPU_VR4122: pclock = 18432000 * 98; break; case CPU_VR4131: pclock = 18432000 * 108; break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } pclock /= CLKSP(clkspeed); printk(KERN_INFO "PClock: %ldHz\n", pclock); return pclock; } static inline unsigned long calculate_vtclock(u16 clkspeed, unsigned long pclock) { switch (mips_cpu.cputype) { case CPU_VR4111: /* The NEC VR4111 doesn't have the VTClock. */ break; case CPU_VR4121: vr41xx_vtclock = pclock; /* DIVVT == 9 Divide by 1.5 . VTClock = (PClock * 6) / 9 */ if (DIVVT(clkspeed) == 9) vr41xx_vtclock = pclock * 6; /* DIVVT == 10 Divide by 2.5 . VTClock = (PClock * 4) / 10 */ else if (DIVVT(clkspeed) == 10) vr41xx_vtclock = pclock * 4; vr41xx_vtclock /= DIVVT(clkspeed); printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); break; case CPU_VR4122: if(VTDIVMODE(clkspeed) == 7) vr41xx_vtclock = pclock / 1; else if(VTDIVMODE(clkspeed) == 1) vr41xx_vtclock = pclock / 2; else vr41xx_vtclock = pclock / VTDIVMODE(clkspeed); printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); break; case CPU_VR4131: vr41xx_vtclock = pclock / VTDIVMODE(clkspeed); printk(KERN_INFO "VTClock: %ldHz\n", vr41xx_vtclock); break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } return vr41xx_vtclock; } static inline unsigned long calculate_tclock(u16 clkspeed, unsigned long pclock, unsigned long vtclock) { unsigned long tclock = 0; switch (mips_cpu.cputype) { case CPU_VR4111: if (!(clkspeed & DIV2B)) tclock = pclock / 2; else if (!(clkspeed & DIV3B)) tclock = pclock / 3; else if (!(clkspeed & DIV4B)) tclock = pclock / 4; break; case CPU_VR4121: tclock = pclock / DIVT(clkspeed); break; case CPU_VR4122: case CPU_VR4131: tclock = vtclock / TDIVMODE(clkspeed); break; default: printk(KERN_INFO "Unexpected CPU of NEC VR4100 series\n"); break; } printk(KERN_INFO "TClock: %ldHz\n", tclock); return tclock; } static inline unsigned long calculate_mips_counter_frequency(unsigned long tclock) { /* * VR4131 Revision 2.0 and 2.1 use a value of (tclock / 2). */ if ((mips_cpu.cputype == CPU_VR4131) && (((mips_cpu.processor_id & 0xff) == PRID_REV_VR4131_REV2_0) || ((mips_cpu.processor_id & 0xff) == PRID_REV_VR4131_REV2_1))) tclock /= 2; else tclock /= 4; return tclock; } void __init vr41xx_bcu_init(void) { unsigned long pclock, vtclock, tclock; u16 clkspeed; clkspeed = read_clkspeed(); pclock = calculate_pclock(clkspeed); vtclock = calculate_vtclock(clkspeed, pclock); tclock = calculate_tclock(clkspeed, pclock, vtclock); mips_counter_frequency = calculate_mips_counter_frequency(tclock); } --- NEW FILE: giu.c --- /* * FILE NAME * arch/mips/vr41xx/common/giu.c * * BRIEF MODULE DESCRIPTION * General-purpose I/O Unit Interrupt routines for NEC VR4100 series. * * Author: Yoichi Yuasa * yy...@mv... or so...@mv... * * Copyright 2002 MontaVista Software Inc. * * 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. */ /* * Changes: * MontaVista Software Inc. <yy...@mv...> or <so...@mv...> * - New creation, NEC VR4111, VR4121, VR4122 and VR4131 are supported. */ #include <linux/errno.h> #include <linux/init.h> #include <linux/irq.h> #include <linux/kernel.h> #include <linux/types.h> #include <asm/addrspace.h> #include <asm/cpu.h> #include <asm/io.h> #include <asm/vr41xx.h> #define VR4111_GIUIOSELL KSEG1ADDR(0x0b000100) #define VR4122_GIUIOSELL KSEG1ADDR(0x0f000140) #define GIUIOSELL 0x00 #define GIUIOSELH 0x02 #define GIUINTSTATL 0x08 #define GIUINTSTATH 0x0a #define GIUINTENL 0x0c #define GIUINTENH 0x0e #define GIUINTTYPL 0x10 #define GIUINTTYPH 0x12 #define GIUINTALSELL 0x14 #define GIUINTALSELH 0x16 #define GIUINTHTSELL 0x18 #define GIUINTHTSELH 0x1a u32 vr41xx_giu_base = 0; #define read_giuint(offset) readw(vr41xx_giu_base + (offset)) #define write_giuint(val, offset) writew((val), vr41xx_giu_base + (offset)) static inline u16 set_giuint(u16 offset, u16 set) { u16 res; res = read_giuint(offset); res |= set; write_giuint(res, offset); return res; } static inline u16 clear_giuint(u16 offset, u16 clear) { u16 res; res = read_giuint(offset); res &= ~clear; write_giuint(res, offset); return res; } void vr41xx_enable_giuint(u8 pin) { if (pin < 16) set_giuint(GIUINTENL, (u16)1 << pin); else set_giuint(GIUINTENH, (u16)1 << (pin - 16)); } void vr41xx_disable_giuint(u8 pin) { if (pin < 16) clear_giuint(GIUINTENL, (u16)1 << pin); else clear_giuint(GIUINTENH, (u16)1 << (pin - 16)); } void vr41xx_clear_giuint(u8 pin) { if (pin < 16) write_giuint(GIUINTSTATL, (u16)1 << pin); else write_giuint(GIUINTSTATH, (u16)1 << (pin - 16)); } void vr41xx_set_irq_trigger(u8 pin, u8 trigger, u8 hold) { u16 mask; if (pin < 16) { mask = (u16)1 << pin; if (trigger == TRIGGER_EDGE) { set_giuint(GIUINTTYPL, mask); if (hold == SIGNAL_HOLD) set_giuint(GIUINTHTSELL, mask); else clear_giuint(GIUINTHTSELL, mask); } else { clear_giuint(GIUINTTYPL, mask); clear_giuint(GIUINTHTSELL, mask); } } else { mask = (u16)1 << (pin - 16); if (trigger == TRIGGER_EDGE) { set_giuint(GIUINTTYPH, mask); if (hold == SIGNAL_HOLD) set_giuint(GIUINTHTSELH, mask); else clear_giuint(GIUINTHTSELH, mask); } else { clear_giuint(GIUINTTYPH, mask); clear_giuint(GIUINTHTSELH, mask); } } vr41xx_clear_giuint(pin); } void vr41xx_set_irq_level(u8 pin, u8 level) { u16 mask; if (pin < 16) { mask = (u16)1 << pin; if (level == LEVEL_HIGH) set_giuint(GIUINTALSELL, mask); else clear_giuint(GIUINTALSELL, mask); } else { mask = (u16)1 << (pin - 16); if (level == LEVEL_HIGH) set_giuint(GIUINTALSELH, mask); else clear_giuint(GIUINTALSELH, mask); } vr41xx_clear_giuint(pin); } #define GIUINT_CASCADE_IRQ 16 #define GIUINT_NR_IRQS 32 enum { GIUINT_NO_CASCADE, GIUINT_CASCADE }; struct vr41xx_giuint_cascade { unsigned int flag; int (*get_irq_number)(int irq); }; static struct vr41xx_giuint_cascade giuint_cascade[GIUINT_NR_IRQS]; static struct irqaction giu_cascade = {no_action, 0, 0, "cascade", NULL, NULL}; static int no_irq_number(int irq) { return -EINVAL; } int vr41xx_cascade_irq(unsigned int irq, int (*get_irq_number)(int irq)) { unsigned int pin; int retval; if (irq < GIU_IRQ(0) || irq > GIU_IRQ(31)) return -EINVAL; if(!get_irq_number) return -EINVAL; pin = irq - GIU_IRQ(0); giuint_cascade[pin].flag = GIUINT_CASCADE; giuint_cascade[pin].get_irq_number = get_irq_number; retval = setup_irq(irq, &giu_cascade); if (retval) { giuint_cascade[pin].flag = GIUINT_NO_CASCADE; giuint_cascade[pin].get_irq_number = no_irq_number; } return retval; } extern unsigned int do_IRQ(int irq, struct pt_regs *regs); unsigned int giuint_do_IRQ(int pin, struct pt_regs *regs) { struct vr41xx_giuint_cascade *cascade; unsigned int retval = 0; int giuint_irq, cascade_irq; disable_irq(GIUINT_CASCADE_IRQ); cascade = &giuint_cascade[pin]; giuint_irq = pin + GIU_IRQ(0); if (cascade->flag == GIUINT_CASCADE) { cascade_irq = cascade->get_irq_number(giuint_irq); disable_irq(giuint_irq); if (cascade_irq > 0) retval = do_IRQ(cascade_irq, regs); enable_irq(giuint_irq); } else retval = do_IRQ(giuint_irq, regs); enable_irq(GIUINT_CASCADE_IRQ); return retval; } void (*board_irq_init)(void) = NULL; void __init vr41xx_giuint_init(void) { int i; switch (mips_cpu.cputype) { case CPU_VR4111: case CPU_VR4121: vr41xx_giu_base = VR4111_GIUIOSELL; break; case CPU_VR4122: case CPU_VR4131: vr41xx_giu_base = VR4122_GIUIOSELL; break; default: panic("GIU: Unexpected CPU of NEC VR4100 series"); break; } for (i = 0; i < GIUINT_NR_IRQS; i++) { vr41xx_disable_giuint(i); giuint_cascade[i].flag = GIUINT_NO_CASCADE; giuint_cascade[i].get_irq_number = no_irq_number; } if (setup_irq(GIUINT_CASCADE_IRQ, &giu_cascade)) printk("GIUINT: Can not cascade IRQ %d.\n", GIUINT_CASCADE_IRQ); if (board_irq_init) board_irq_init(); } --- NEW FILE: icu.c --- /* * FILE NAME * arch/mips/vr41xx/vr4122/common/icu.c * * BRIEF MODULE DESCRIPTION * Interrupt Control Unit routines for the NEC VR4122 and VR4131. * * Author: Yoichi Yuasa * yy...@mv... or so...@mv... * * Copyright 2001,2002 MontaVista Software Inc. * * 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. */ /* * Changes: * MontaVista Software Inc. <yy...@mv...> or <so...@mv...> * - Added support for NEC VR4111 and VR4121. * * Paul Mundt <le...@ch...> * - kgdb support. * * MontaVista Software Inc. <yy...@mv...> or <so...@mv...> * - New creation, NEC VR4122 and VR4131 are supported. */ #include <linux/errno.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/irq.h> #include <linux/types.h> #include <asm/addrspace.h> #include <asm/cpu.h> #include <asm/gdb-stub.h> #include <asm/io.h> #include <asm/mipsregs.h> #include <asm/vr41xx.h> #define MIPS_CPU_IRQ_BASE 0 #define SYSINT1_IRQ_BASE 8 #define SYSINT1_IRQ_LAST 23 #define SYSINT2_IRQ_BASE 24 #define SYSINT2_IRQ_LAST 39 #define GIUINT_IRQ_BASE GIU_IRQ(0) #define GIUINT_IRQ_LAST GIU_IRQ(31) #define ICU_CASCADE_IRQ (MIPS_CPU_IRQ_BASE + 2) extern asmlinkage void vr41xx_handle_interrupt(void); extern void __init init_generic_irq(void); extern void mips_cpu_irq_init(u32 irq_base); extern unsigned int do_IRQ(int irq, struct pt_regs *regs); extern void vr41xx_giuint_init(void); extern unsigned int giuint_do_IRQ(int pin, struct pt_regs *regs); static u32 vr41xx_icu1_base = 0; static u32 vr41xx_icu2_base = 0; #define VR4111_SYSINT1REG KSEG1ADDR(0x0b000080) #define VR4111_SYSINT2REG KSEG1ADDR(0x0b000200) #define VR4122_SYSINT1REG KSEG1ADDR(0x0f000080) #define VR4122_SYSINT2REG KSEG1ADDR(0x0f0000a0) #define SYSINT1REG 0x00 #define GIUINTLREG 0x08 #define MSYSINT1REG 0x0c #define MGIUINTLREG 0x14 #define NMIREG 0x18 #define SOFTREG 0x1a #define SYSINT2REG 0x00 #define GIUINTHREG 0x02 #define MSYSINT2REG 0x06 #define MGIUINTHREG 0x08 #define read_icu1(offset) readw(vr41xx_icu1_base + (offset)) #define write_icu1(val, offset) writew((val), vr41xx_icu1_base + (offset)) #define read_icu2(offset) readw(vr41xx_icu2_base + (offset)) #define write_icu2(val, offset) writew((val), vr41xx_icu2_base + (offset)) static inline u16 set_icu1(u16 offset, u16 set) { u16 res; res = read_icu1(offset); res |= set; write_icu1(res, offset); return res; } static inline u16 clear_icu1(u16 offset, u16 clear) { u16 res; res = read_icu1(offset); res &= ~clear; write_icu1(res, offset); return res; } static inline u16 set_icu2(u16 offset, u16 set) { u16 res; res = read_icu2(offset); res |= set; write_icu2(res, offset); return res; } static inline u16 clear_icu2(u16 offset, u16 clear) { u16 res; res = read_icu2(offset); res &= ~clear; write_icu2(res, offset); return res; } /*=======================================================================*/ static void enable_sysint1_irq(unsigned int irq) { set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); } static void disable_sysint1_irq(unsigned int irq) { clear_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); } static unsigned int startup_sysint1_irq(unsigned int irq) { set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); return 0; /* never anything pending */ } #define shutdown_sysint1_irq disable_sysint1_irq #define ack_sysint1_irq disable_sysint1_irq static void end_sysint1_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) set_icu1(MSYSINT1REG, (u16)1 << (irq - SYSINT1_IRQ_BASE)); } static struct hw_interrupt_type sysint1_irq_type = { "SYSINT1", startup_sysint1_irq, shutdown_sysint1_irq, enable_sysint1_irq, disable_sysint1_irq, ack_sysint1_irq, end_sysint1_irq, NULL }; /*=======================================================================*/ static void enable_sysint2_irq(unsigned int irq) { set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); } static void disable_sysint2_irq(unsigned int irq) { clear_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); } static unsigned int startup_sysint2_irq(unsigned int irq) { set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); return 0; /* never anything pending */ } #define shutdown_sysint2_irq disable_sysint2_irq #define ack_sysint2_irq disable_sysint2_irq static void end_sysint2_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) set_icu2(MSYSINT2REG, (u16)1 << (irq - SYSINT2_IRQ_BASE)); } static struct hw_interrupt_type sysint2_irq_type = { "SYSINT2", startup_sysint2_irq, shutdown_sysint2_irq, enable_sysint2_irq, disable_sysint2_irq, ack_sysint2_irq, end_sysint2_irq, NULL }; /*=======================================================================*/ extern void vr41xx_enable_giuint(u8 pin); extern void vr41xx_disable_giuint(u8 pin); extern void vr41xx_clear_giuint(u8 pin); static void enable_giuint_irq(unsigned int irq) { u8 pin; pin = irq - GIUINT_IRQ_BASE; if (pin < 16) set_icu1(MGIUINTLREG, (u16)1 << pin); else set_icu2(MGIUINTHREG, (u16)1 << (pin - 16)); vr41xx_enable_giuint(pin); } static void disable_giuint_irq(unsigned int irq) { u8 pin; pin = irq - GIUINT_IRQ_BASE; vr41xx_disable_giuint(pin); if (pin < 16) clear_icu1(MGIUINTLREG, (u16)1 << pin); else clear_icu2(MGIUINTHREG, (u16)1 << (pin - 16)); } static unsigned int startup_giuint_irq(unsigned int irq) { vr41xx_clear_giuint(irq - GIUINT_IRQ_BASE); enable_giuint_irq(irq); return 0; /* never anything pending */ } #define shutdown_giuint_irq disable_giuint_irq static void ack_giuint_irq(unsigned int irq) { disable_giuint_irq(irq); vr41xx_clear_giuint(irq - GIUINT_IRQ_BASE); } static void end_giuint_irq(unsigned int irq) { if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) enable_giuint_irq(irq); } static struct hw_interrupt_type giuint_irq_type = { "GIUINT", startup_giuint_irq, shutdown_giuint_irq, enable_giuint_irq, disable_giuint_irq, ack_giuint_irq, end_giuint_irq, NULL }; /*=======================================================================*/ static struct irqaction icu_cascade = {no_action, 0, 0, "cascade", NULL, NULL}; static void __init vr41xx_icu_init(void) { int i; switch (mips_cpu.cputype) { case CPU_VR4111: case CPU_VR4121: vr41xx_icu1_base = VR4111_SYSINT1REG; vr41xx_icu2_base = VR4111_SYSINT2REG; break; case CPU_VR4122: case CPU_VR4131: vr41xx_icu1_base = VR4122_SYSINT1REG; vr41xx_icu2_base = VR4122_SYSINT2REG; break; default: panic("Unexpected CPU of NEC VR4100 series"); break; } write_icu1(0, MSYSINT1REG); write_icu1(0, MGIUINTLREG); write_icu2(0, MSYSINT2REG); write_icu2(0, MGIUINTHREG); for (i = SYSINT1_IRQ_BASE; i <= GIUINT_IRQ_LAST; i++) { if (i >= SYSINT1_IRQ_BASE && i <= SYSINT1_IRQ_LAST) irq_desc[i].handler = &sysint1_irq_type; else if (i >= SYSINT2_IRQ_BASE && i <= SYSINT2_IRQ_LAST) irq_desc[i].handler = &sysint2_irq_type; else if (i >= GIUINT_IRQ_BASE && i <= GIUINT_IRQ_LAST) irq_desc[i].handler = &giuint_irq_type; } setup_irq(ICU_CASCADE_IRQ, &icu_cascade); } void __init init_IRQ(void) { memset(irq_desc, 0, sizeof(irq_desc)); init_generic_irq(); mips_cpu_irq_init(MIPS_CPU_IRQ_BASE); vr41xx_icu_init(); vr41xx_giuint_init(); set_except_vector(0, vr41xx_handle_interrupt); #ifdef CONFIG_REMOTE_DEBUG printk("Setting debug traps - please connect the remote debugger.\n"); set_debug_traps(); breakpoint(); #endif } /*=======================================================================*/ static inline void giuint_irqdispatch(u16 pendl, u16 pendh, struct pt_regs *regs) { int i; if (pendl) { for (i = 0; i < 16; i++) { if (pendl & (0x0001 << i)) { giuint_do_IRQ(i, regs); return; } } } else if (pendh) { for (i = 0; i < 16; i++) { if (pendh & (0x0001 << i)) { giuint_do_IRQ(i + 16, regs); return; } } } } asmlinkage void icu_irqdispatch(struct pt_regs *regs) { u16 pend1, pend2, pendl, pendh; u16 mask1, mask2, maskl, maskh; int i; pend1 = read_icu1(SYSINT1REG); mask1 = read_icu1(MSYSINT1REG); pend2 = read_icu2(SYSINT2REG); mask2 = read_icu2(MSYSINT2REG); pendl = read_icu1(GIUINTLREG); maskl = read_icu1(MGIUINTLREG); pendh = read_icu2(GIUINTHREG); maskh = read_icu2(MGIUINTHREG); pend1 &= mask1; pend2 &= mask2; pendl &= maskl; pendh &= maskh; if (pend1) { if ((pend1 & 0x01ff) == 0x0100) { giuint_irqdispatch(pendl, pendh, regs); } else { for (i = 0; i < 16; i++) { if (pend1 & (0x0001 << i)) { do_IRQ(SYSINT1_IRQ_BASE + i, regs); break; } } } return; } else if (pend2) { for (i = 0; i < 16; i++) { if (pend2 & (0x0001 << i)) { do_IRQ(SYSINT2_IRQ_BASE + i, regs); break; } } } } Index: Makefile =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/vr41xx/common/Makefile,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- Makefile 14 Jun 2002 15:02:14 -0000 1.8 +++ Makefile 12 Jul 2002 20:14:27 -0000 1.9 @@ -15,8 +15,9 @@ O_TARGET := vr41xx.o -obj-y := int-handler.o reset.o irq.o +obj-y := bcu.o cmu.o giu.o icu.o int-handler.o reset.o +obj-$(CONFIG_SERIAL) += serial.o obj-$(CONFIG_VR41XX_TIME_C) += time.o obj-$(CONFIG_VR41XX_LED) += led.o Index: time.c =================================================================== RCS file: /cvsroot/linux-mips/linux/arch/mips/vr41xx/common/time.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- time.c 7 Mar 2002 03:16:53 -0000 1.3 +++ time.c 12 Jul 2002 20:14:27 -0000 1.4 @@ -33,6 +33,9 @@ /* * Changes: * MontaVista Software Inc. <yy...@mv...> or <so...@mv...> + * - Added support for NEC VR4100 series RTC Unit. + * + * MontaVista Software Inc. <yy...@mv...> or <so...@mv...> * - New creation, NEC VR4100 series are supported. */ #include <linux/config.h> @@ -40,6 +43,7 @@ #include <linux/irq.h> #include <linux/types.h> +#include <asm/cpu.h> #include <asm/io.h> #include <asm/mipsregs.h> #include <asm/param.h> @@ -47,19 +51,37 @@ #define MIPS_COUNTER_TIMER_IRQ 7 +#define VR4111_ETIMELREG KSEG1ADDR(0x0b0000c0) +#define VR4122_ETIMELREG KSEG1ADDR(0x0f000100) + +u32 vr41xx_rtc_base = 0; + #ifdef CONFIG_VR41XX_RTC extern unsigned long vr41xx_rtc_get_time(void); -extern int vr41xx_rtc_set_time(unsigned long); +extern int vr41xx_rtc_set_time(unsigned long sec); #endif void vr41xx_time_init(void) { + switch (mips_cpu.cputype) { + case CPU_VR4111: + case CPU_VR4121: + vr41xx_rtc_base = VR4111_ETIMELREG; + break; + case CPU_VR4122: + case CPU_VR4131: + vr41xx_rtc_base = VR4122_ETIMELREG; + break; + default: + panic("Unexpected CPU of NEC VR4100 series"); + break; + } + #ifdef CONFIG_VR41XX_RTC - rtc_get_time = vr41xx_rtc_get_time; - rtc_set_time = vr41xx_rtc_set_time; + rtc_get_time = vr41xx_rtc_get_time; + rtc_set_time = vr41xx_rtc_set_time; #endif } - void vr41xx_timer_setup(struct irqaction *irq) { --- irq.c DELETED --- |