diff options
Diffstat (limited to 'arch/mips/dec/time.c')
| -rw-r--r-- | arch/mips/dec/time.c | 113 |
1 files changed, 52 insertions, 61 deletions
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c index 60349062595..1914e56f0d9 100644 --- a/arch/mips/dec/time.c +++ b/arch/mips/dec/time.c @@ -1,6 +1,4 @@ /* - * linux/arch/mips/dec/time.c - * * Copyright (C) 1991, 1992, 1995 Linus Torvalds * Copyright (C) 2000, 2003 Maciej W. Rozycki * @@ -9,33 +7,18 @@ * */ #include <linux/bcd.h> -#include <linux/errno.h> #include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> #include <linux/mc146818rtc.h> -#include <linux/mm.h> -#include <linux/module.h> #include <linux/param.h> -#include <linux/sched.h> -#include <linux/string.h> -#include <linux/time.h> -#include <linux/types.h> - -#include <asm/bootinfo.h> -#include <asm/cpu.h> -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/mipsregs.h> -#include <asm/sections.h> -#include <asm/time.h> +#include <asm/cpu-features.h> +#include <asm/ds1287.h> +#include <asm/time.h> #include <asm/dec/interrupts.h> #include <asm/dec/ioasic.h> -#include <asm/dec/ioasic_addrs.h> #include <asm/dec/machtype.h> -unsigned long read_persistent_clock(void) +void read_persistent_clock(struct timespec *ts) { unsigned int year, mon, day, hour, min, sec, real_year; unsigned long flags; @@ -60,17 +43,18 @@ unsigned long read_persistent_clock(void) spin_unlock_irqrestore(&rtc_lock, flags); if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - sec = BCD2BIN(sec); - min = BCD2BIN(min); - hour = BCD2BIN(hour); - day = BCD2BIN(day); - mon = BCD2BIN(mon); - year = BCD2BIN(year); + sec = bcd2bin(sec); + min = bcd2bin(min); + hour = bcd2bin(hour); + day = bcd2bin(day); + mon = bcd2bin(mon); + year = bcd2bin(year); } year += real_year - 72 + 2000; - return mktime(year, mon, day, hour, min, sec); + ts->tv_sec = mktime(year, mon, day, hour, min, sec); + ts->tv_nsec = 0; } /* @@ -98,7 +82,7 @@ int rtc_mips_set_mmss(unsigned long nowtime) cmos_minutes = CMOS_READ(RTC_MINUTES); if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - cmos_minutes = BCD2BIN(cmos_minutes); + cmos_minutes = bcd2bin(cmos_minutes); /* * since we're only adjusting minutes and seconds, @@ -114,13 +98,13 @@ int rtc_mips_set_mmss(unsigned long nowtime) if (abs(real_minutes - cmos_minutes) < 30) { if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - real_seconds = BIN2BCD(real_seconds); - real_minutes = BIN2BCD(real_minutes); + real_seconds = bin2bcd(real_seconds); + real_minutes = bin2bcd(real_minutes); } CMOS_WRITE(real_seconds, RTC_SECONDS); CMOS_WRITE(real_minutes, RTC_MINUTES); } else { - printk(KERN_WARNING + printk_once(KERN_NOTICE "set_rtc_mmss: can't update from %d to %d\n", cmos_minutes, real_minutes); retval = -1; @@ -139,42 +123,49 @@ int rtc_mips_set_mmss(unsigned long nowtime) return retval; } -static int dec_timer_state(void) +void __init plat_time_init(void) { - return (CMOS_READ(RTC_REG_C) & RTC_PF) != 0; -} + int ioasic_clock = 0; + u32 start, end; + int i = HZ / 8; -static void dec_timer_ack(void) -{ - CMOS_READ(RTC_REG_C); /* Ack the RTC interrupt. */ -} + /* Set up the rate of periodic DS1287 interrupts. */ + ds1287_set_base_clock(HZ); -static cycle_t dec_ioasic_hpt_read(void) -{ - /* - * The free-running counter is 32-bit which is good for about - * 2 minutes, 50 seconds at possible count rates of up to 25MHz. - */ - return ioasic_read(IO_REG_FCTR); -} + /* On some I/O ASIC systems we have the I/O ASIC's counter. */ + if (IOASIC) + ioasic_clock = dec_ioasic_clocksource_init() == 0; + if (cpu_has_counter) { + ds1287_timer_state(); + while (!ds1287_timer_state()) + ; + start = read_c0_count(); -void __init plat_time_init(void) -{ - mips_timer_ack = dec_timer_ack; + while (i--) + while (!ds1287_timer_state()) + ; - if (!cpu_has_counter && IOASIC) - /* For pre-R4k systems we use the I/O ASIC's counter. */ - clocksource_mips.read = dec_ioasic_hpt_read; + end = read_c0_count(); - /* Set up the rate of periodic DS1287 interrupts. */ - CMOS_WRITE(RTC_REF_CLCK_32KHZ | (16 - __ffs(HZ)), RTC_REG_A); -} + mips_hpt_frequency = (end - start) * 8; + printk(KERN_INFO "MIPS counter frequency %dHz\n", + mips_hpt_frequency); -void __init plat_timer_setup(struct irqaction *irq) -{ - setup_irq(dec_interrupt[DEC_IRQ_RTC], irq); + /* + * All R4k DECstations suffer from the CP0 Count erratum, + * so we can't use the timer as a clock source, and a clock + * event both at a time. An accurate wall clock is more + * important than a high-precision interval timer so only + * use the timer as a clock source, and not a clock event + * if there's no I/O ASIC counter available to serve as a + * clock source. + */ + if (!ioasic_clock) { + init_r4k_clocksource(); + mips_hpt_frequency = 0; + } + } - /* Enable periodic DS1287 interrupts. */ - CMOS_WRITE(CMOS_READ(RTC_REG_B) | RTC_PIE, RTC_REG_B); + ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]); } |
