From: Paul M. <le...@us...> - 2001-10-28 23:04:22
|
Update of /cvsroot/linux-mips/linux/arch/mips/vr4111/common In directory usw-pr-cvs1:/tmp/cvs-serv30742/arch/mips/vr4111/common Added Files: Makefile cmu.c icu.c int-handler.S irq.c power.c serial.c time.c Log Message: Merged Vr4111 (Clio-1000) patch from Jim Paris. --- NEW FILE: Makefile --- # # Makefile for common code of NEC vr4111 based boards # # Note! Dependencies are done automagically by 'make dep', which also # removes any old dependencies. DON'T put your own dependencies here # unless it's something special (ie not a .c file). # .S.s: $(CPP) $(CFLAGS) $< -o $*.s .S.o: $(CC) $(CFLAGS) -c $< -o $*.o O_TARGET:= vr4111.o obj-y := irq.o int-handler.o icu.o serial.o time.o power.o cmu.o include $(TOPDIR)/Rules.make --- NEW FILE: cmu.c --- /* * BRIEF MODULE DESCRIPTION * NEC Vr4111 Clock Mask Unit routines. * * Copyright 2001 MontaVista Software Inc. * Author: Yoichi Yuasa * yy...@mv... or so...@mv... * * Adapted to VR4111 from arch/mips/vr4122/common/cmu.c * 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. * * 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/vr41xx.h> void vr4111_clock_supply(unsigned short mask) { *VR41XX_CMUCLKMSK |= mask; } void vr4111_clock_mask(unsigned short mask) { *VR41XX_CMUCLKMSK &= ~mask; } --- NEW FILE: icu.c --- /* * Interrupt dispatcher for VR4111 ICU. * * Based on arch/mips/vr4122/common/icu.c * Copyright 2001 MontaVista Software Inc. * Author: Yoichi Yuasa * yy...@mv... or so...@mv... * * Copyright 2001 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. * * 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> #include <asm/types.h> #include <asm/vr41xx.h> /* * Determine whether it's a SYSINT1, SYSINT2, GIUINTL, or GIUINTH * interrupt, set the base IRQ to the appropriate value and read the * status of the corresponding interrupt register, and then do a * binary search to find which actual IRQ occurred. */ asmlinkage void int0_icu_irqdispatch(struct pt_regs *regs) { u16 pend1, pend2; int irq; u16 search; pend1 = *VR41XX_SYSINT1REG & *VR41XX_MSYSINT1REG; pend2 = *VR41XX_SYSINT2REG & *VR41XX_MSYSINT2REG; if (pend1) { if ((pend1 & 0x01ff) == 0x0100) { /* Handle the GIU interrupt */ pend1 = *VR41XX_GIUINTLREG & *VR41XX_MGIUINTLREG; pend2 = *VR41XX_GIUINTHREG & *VR41XX_MGIUINTHREG; if (pend1) { irq = VR41XX_GIUINTL_IRQ_BASE; search = pend1; /* ... fall through to search */ } else if (pend2) { irq = VR41XX_GIUINTH_IRQ_BASE; search = pend2; /* ... fall through to search */ } else { return; } } else { /* Not a GIU interrupt */ irq = VR41XX_SYSINT1_IRQ_BASE; search = pend1; /* ... fall through to search */ } } else if (pend2) { irq = VR41XX_SYSINT2_IRQ_BASE; search = pend2; /* ... fall through to search */ } else { return; } if(search & 0xFF00) { search >>= 8; irq += 8; } if(search & 0xF0) { search >>= 4; irq += 4; } if(search & 0xC) { search >>= 2; irq += 2; } if(search & 2) { irq += 1; } do_IRQ(irq, regs); } --- NEW FILE: int-handler.S --- /* * 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. * * 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/asm.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> #include <asm/vr41xx.h> .text .set noreorder .align 5 NESTED(vr4111_handle_int, PT_SIZE, ra) .set noat SAVE_ALL CLI .set at .set noreorder /* Get a list of pending interrupts that are not disabled */ 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 1: andi t1, t0, 0x7800 # check for IP3-6 beqz t1, 2f andi t1, t0, CAUSEF_IP3 # check for IP3 (rtc_long1) bnez t1, handle_it li a0, 3 andi t1, t0, CAUSEF_IP4 # check for IP4 (rtc_long2) bnez t1, handle_it li a0, 4 andi t1, t0, CAUSEF_IP5 # check for IP5 (hsp) bnez t1, handle_it li a0, 5 /* 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 */ 2: andi t1, t0, CAUSEF_IP2 # check for IP2 (all other interrupts) beqz t1, 3f move a0, sp jal int0_icu_irqdispatch # in C for implementation ease nop 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 j spurious_interrupt nop handle_it: jal do_IRQ move a1, sp j ret_from_irq END(vr4111_handle_int) --- NEW FILE: irq.c --- /* * arch/mips/vr4111/common/irq.c * * Copyright (C) 2001 MontaVista Software Inc. * Author: Jun Sun, js...@mv... or js...@ju... * * Copyright (C) 2001 Jim Paris <ji...@jt...> * * Credits to Bradley D. LaRonde and Michael Klar for writing the original * irq.c file which was derived from the common irq.c file. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * */ #include <linux/types.h> #include <linux/init.h> #include <linux/kernel_stat.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/interrupt.h> #include <linux/malloc.h> #include <linux/random.h> #include <asm/irq.h> #include <asm/mipsregs.h> #include <asm/gdb-stub.h> #include <asm/vr41xx.h> /* * Strategy: * * We essentially have three irq controllers, CPU, system, and gpio. * * CPU irq controller is taken care by arch/mips/kernel/irq_cpu.c and * CONFIG_IRQ_CPU config option. * * We here provide sys_irq and gpio_irq controller code. */ static int sys_irq_base; static int gpio_irq_base; /* ---------------------- sys irq ------------------------ */ 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); } else { irq -= 16; *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)); } else { irq -= 16; *VR41XX_MSYSINT2REG &= ~((u16)(1 << irq)); } } static unsigned int sys_irq_startup(unsigned int irq) { sys_irq_enable(irq); return 0; } #define sys_irq_shutdown sys_irq_disable #define sys_irq_ack sys_irq_disable #define sys_irq_end sys_irq_enable static hw_irq_controller sys_irq_controller = { "vr4111_sys_irq", sys_irq_startup, sys_irq_shutdown, sys_irq_enable, sys_irq_disable, sys_irq_ack, sys_irq_end, NULL /* no affinity stuff for UP */ }; /* ---------------------- gpio irq ------------------------ */ 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); } else { irq -= 16; if(*VR41XX_GIUINTTYPH & ((u16)1 << irq)) *VR41XX_GIUINTSTATH = ((u16)1 << irq); } } static void gpio_irq_enable(unsigned int irq) { gpio_irq_clear(irq); irq -= gpio_irq_base; if (irq < 16) { *VR41XX_MGIUINTLREG |= (u16)(1 << irq); } else { irq -= 16; *VR41XX_MGIUINTHREG |= (u16)(1 << irq); } } static void gpio_irq_disable(unsigned int irq) { irq -= gpio_irq_base; if (irq < 16) { *VR41XX_MGIUINTLREG &= ~((u16)(1 << irq)); } else { irq -= 16; *VR41XX_MGIUINTHREG &= ~((u16)(1 << irq)); } } static unsigned int 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)); } } static void gpio_irq_ack(unsigned int irq) { gpio_irq_disable(irq); gpio_irq_clear(irq); } #define gpio_irq_end gpio_irq_enable static hw_irq_controller gpio_irq_controller = { "vr4111_gpio_irq", gpio_irq_startup, gpio_irq_shutdown, gpio_irq_enable, gpio_irq_disable, gpio_irq_ack, gpio_irq_end, NULL /* no affinity stuff for UP */ }; /* --------------------- IRQ init stuff ---------------------- */ extern asmlinkage void vr4111_handle_int(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[]; init_generic_irq(); mips_cpu_irq_init(VR41XX_CPU_IRQ_BASE); /* init sys irqs */ sys_irq_base = VR41XX_SYS_IRQ_BASE; for (i=sys_irq_base; i < sys_irq_base + VR41XX_NUM_SYS_IRQ; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].handler = &sys_irq_controller; } /* init gpio irqs */ gpio_irq_base = VR41XX_GPIO_IRQ_BASE; for (i=gpio_irq_base; i < gpio_irq_base + VR41XX_NUM_GPIO_IRQ; i++) { irq_desc[i].status = IRQ_DISABLED; irq_desc[i].action = NULL; irq_desc[i].depth = 1; irq_desc[i].handler = &gpio_irq_controller; } /* Default all ICU IRQs to off ... */ *VR41XX_MSYSINT1REG = 0; *VR41XX_MSYSINT2REG = 0; /* We initialize the level 2 ICU registers to all bits disabled. */ *VR41XX_MPIUINTREG = 0; *VR41XX_MAIUINTREG = 0; *VR41XX_MKIUINTREG = 0; *VR41XX_MDSIUINTREG = 0; *VR41XX_MFIRINTREG = 0; *VR41XX_MGIUINTLREG = 0; *VR41XX_MGIUINTHREG = 0; /* Disable and clear all GPIO interrupts */ *VR41XX_GIUINTENL = 0; *VR41XX_GIUINTENH = 0; *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); #ifdef CONFIG_REMOTE_DEBUG printk("Setting debug traps - please connect the remote debugger.\n"); set_debug_traps(); breakpoint(); #endif } --- NEW FILE: power.c --- /* * VR4111 reset and power management type stuff * * Copyright (C) 2000 Michael Klar * * Copyright (C) 2001 Jim Paris <ji...@jt...> * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/config.h> #include <linux/delay.h> #include <linux/mm.h> #include <linux/sysctl.h> #include <linux/pm.h> #include <linux/acpi.h> #include <linux/irq.h> /* for disable_irq, enable_irq, to be removed */ #include <asm/vr41xx.h> #include <asm/cacheops.h> #include <asm/mipsregs.h> #include <asm/pgalloc.h> #include <asm/power.h> /* * vr4111_dma_sem is needed because we cannot suspend while a DMA transfer * is in progress, otherwise the CPU will be left in an undefined state. */ extern struct semaphore vr4111_dma_sem; void vr4111_wait(void) { /* Use "standby" instead of "wait" on VR4111. */ asm volatile ( ".set noreorder\n" "standby\n" "nop\n" "nop\n" "nop\n" ".set reorder\n" ); } void vr4111_hibernate(void) { asm volatile ( " .set noreorder\n" " .align 4\n" " hibernate\n" " nop\n" " nop\n" " nop\n" " .set reorder\n" ); } static inline void vr4111_suspend(void) { asm volatile ( " .set noreorder\n" " .align 4\n" " suspend\n" " nop\n" " nop\n" " nop\n" " .set reorder\n" ); } static inline void vr4111_standby(void) { asm volatile ( " .set noreorder\n" " .align 4\n" " standby\n" " nop\n" " nop\n" " nop\n" " .set reorder\n" ); } --- NEW FILE: serial.c --- /* * Copyright 2001 MontaVista Software Inc. * Author: Jun Sun, js...@mv... or js...@ju... * * arch/mips/vr4111/common/serial.c * initialize serial port on vr4111. * * Adapted to the VR4111 from arch/mips/vr4181/common/serial.c * Copyright (C) 2001 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. * */ /* * [jsun, 010925] * You need to make sure rs_table has at least one element in * drivers/char/serial.c file. There is no good way to do it right * now. A workaround is to include CONFIG_SERIAL_MANY_PORTS in your * configure file, which would gives you 64 ports and wastes 11K ram. */ #include <linux/config.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/serial.h> #include <asm/string.h> #include <asm/io.h> #include <asm/vr41xx.h> void __init vr4111_init_serial(void) { struct serial_struct s; unsigned short val; /* Ensure that serial is set to RS-232C (not IrDA) */ *VR41XX_SIUIRSEL &= ~VR41XX_SIUIRSEL_SIRSEL; /* Supply clocks to all serial units */ vr4111_clock_supply(VR41XX_CMUCLKMSK_MSKSIU); vr4111_clock_supply(VR41XX_CMUCLKMSK_MSKDSIU); vr4111_clock_supply(VR41XX_CMUCLKMSK_MSKSSIU); memset(&s, 0, sizeof(s)); s.line = 0; s.baud_base = 1152000; s.irq = VR41XX_IRQ_SIU; s.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; /* STD_COM_FLAGS */ s.iomem_base = (u8*)VR41XX_SIURB; s.iomem_reg_shift = 0; s.io_type = SERIAL_IO_MEM; if (early_serial_setup(&s) != 0) { panic("vr4111_init_serial() failed!\n"); } } --- NEW FILE: time.c --- /* * BRIEF MODULE DESCRIPTION * NEC Vr4111 RTC Unit routines. * * Copyright 2001 MontaVista Software Inc. * Author: Yoichi Yuasa * yy...@mv... or so...@mv... * * Adapted to the VR4111 from arch/mips/vr4122/common/time.c * 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. * * 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/spinlock.h> #include <linux/config.h> #include <linux/irq.h> #include <asm/io.h> #include <asm/time.h> #include <asm/vr41xx.h> spinlock_t vr4111_rtc_lock = SPIN_LOCK_UNLOCKED; static inline unsigned short read_etime_register(volatile unsigned short *addr) { unsigned short val; do { val = *addr; } while (val != *addr); return val; } static unsigned long vr4111_rtc_get_time(void) { unsigned short etimel, etimem, etimeh; do { etimem = read_etime_register(VR41XX_ETIMEMREG); etimeh = read_etime_register(VR41XX_ETIMEHREG); etimel = read_etime_register(VR41XX_ETIMELREG); } while (etimem != read_etime_register(VR41XX_ETIMEMREG)); return ((etimeh << 17) | (etimem << 1) | (etimel >> 15)); } static int vr4111_rtc_set_time(unsigned long sec) { unsigned long flags; spin_lock_irqsave(&vr4111_rtc_lock, flags); *VR41XX_ETIMELREG = sec << 15; *VR41XX_ETIMEMREG = sec >> 1; *VR41XX_ETIMEHREG = sec >> 17; spin_unlock_irqrestore(&vr4111_rtc_lock, flags); return 0; } void vr4111_time_init(void) { unsigned long clock; unsigned short val; rtc_get_time = vr4111_rtc_get_time; rtc_set_time = vr4111_rtc_set_time; /* If it's not already set (by board-specific code), figure out the counter frequency from the clock speed register */ if(mips_counter_frequency) return; val = *VR41XX_CLKSPEEDREG; if((val & 0x1f)==0) panic("can't determine core clock clock: divide by zero!\n"); clock = (18432000 * 64) / (val & 0x1f); printk("CPU core clock: %ldHz\n",clock); switch((~val) & 0xE000) { case 0x8000: clock = clock / 2; break; case 0x4000: clock = clock / 3; break; case 0x2000: clock = clock / 4; break; default: panic("can't determine peripheral clock: unknown divisor!\n"); } printk("Peripheral unit clock: %ldHz\n",clock); mips_counter_frequency = clock / 4; } void vr4111_timer_setup(struct irqaction *irq) { unsigned int count; count = read_32bit_cp0_register(CP0_COUNT); write_32bit_cp0_register (CP0_COMPARE, count + (mips_counter_frequency / HZ)); setup_irq(VR41XX_IRQ_TIMER, irq); } |