xref: /openbmc/linux/arch/alpha/kernel/time.c (revision 3e5c1240)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  linux/arch/alpha/kernel/time.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Copyright (C) 1991, 1992, 1995, 1999, 2000  Linus Torvalds
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  * This file contains the PC-specific time handling details:
71da177e4SLinus Torvalds  * reading the RTC at bootup, etc..
81da177e4SLinus Torvalds  * 1994-07-02    Alan Modra
91da177e4SLinus Torvalds  *	fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
101da177e4SLinus Torvalds  * 1995-03-26    Markus Kuhn
111da177e4SLinus Torvalds  *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
121da177e4SLinus Torvalds  *      precision CMOS clock update
131da177e4SLinus Torvalds  * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
141da177e4SLinus Torvalds  *		"A Kernel Model for Precision Timekeeping" by Dave Mills
151da177e4SLinus Torvalds  * 1997-01-09    Adrian Sun
161da177e4SLinus Torvalds  *      use interval timer if CONFIG_RTC=y
171da177e4SLinus Torvalds  * 1997-10-29    John Bowman (bowman@math.ualberta.ca)
181da177e4SLinus Torvalds  *      fixed tick loss calculation in timer_interrupt
191da177e4SLinus Torvalds  *      (round system clock to nearest tick instead of truncating)
201da177e4SLinus Torvalds  *      fixed algorithm in time_init for getting time from CMOS clock
211da177e4SLinus Torvalds  * 1999-04-16	Thorsten Kranzkowski (dl8bcu@gmx.net)
221da177e4SLinus Torvalds  *	fixed algorithm in do_gettimeofday() for calculating the precise time
231da177e4SLinus Torvalds  *	from processor cycle counter (now taking lost_ticks into account)
241da177e4SLinus Torvalds  * 2000-08-13	Jan-Benedict Glaw <jbglaw@lug-owl.de>
251da177e4SLinus Torvalds  * 	Fixed time_init to be aware of epoches != 1900. This prevents
261da177e4SLinus Torvalds  * 	booting up in 2048 for me;) Code is stolen from rtc.c.
271da177e4SLinus Torvalds  * 2003-06-03	R. Scott Bailey <scott.bailey@eds.com>
281da177e4SLinus Torvalds  *	Tighten sanity in time_init from 1% (10,000 PPM) to 250 PPM
291da177e4SLinus Torvalds  */
301da177e4SLinus Torvalds #include <linux/errno.h>
311da177e4SLinus Torvalds #include <linux/module.h>
321da177e4SLinus Torvalds #include <linux/sched.h>
331da177e4SLinus Torvalds #include <linux/kernel.h>
341da177e4SLinus Torvalds #include <linux/param.h>
351da177e4SLinus Torvalds #include <linux/string.h>
361da177e4SLinus Torvalds #include <linux/mm.h>
371da177e4SLinus Torvalds #include <linux/delay.h>
381da177e4SLinus Torvalds #include <linux/ioport.h>
391da177e4SLinus Torvalds #include <linux/irq.h>
401da177e4SLinus Torvalds #include <linux/interrupt.h>
411da177e4SLinus Torvalds #include <linux/init.h>
421da177e4SLinus Torvalds #include <linux/bcd.h>
431da177e4SLinus Torvalds #include <linux/profile.h>
44e360adbeSPeter Zijlstra #include <linux/irq_work.h>
451da177e4SLinus Torvalds 
461da177e4SLinus Torvalds #include <asm/uaccess.h>
471da177e4SLinus Torvalds #include <asm/io.h>
481da177e4SLinus Torvalds #include <asm/hwrpb.h>
491da177e4SLinus Torvalds #include <asm/8253pit.h>
505f7dc5d7SIvan Kokshaysky #include <asm/rtc.h>
511da177e4SLinus Torvalds 
521da177e4SLinus Torvalds #include <linux/mc146818rtc.h>
531da177e4SLinus Torvalds #include <linux/time.h>
541da177e4SLinus Torvalds #include <linux/timex.h>
559ce34c8fSJohn Stultz #include <linux/clocksource.h>
561da177e4SLinus Torvalds 
571da177e4SLinus Torvalds #include "proto.h"
581da177e4SLinus Torvalds #include "irq_impl.h"
591da177e4SLinus Torvalds 
601da177e4SLinus Torvalds static int set_rtc_mmss(unsigned long);
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds DEFINE_SPINLOCK(rtc_lock);
63cff52dafSAl Viro EXPORT_SYMBOL(rtc_lock);
641da177e4SLinus Torvalds 
651da177e4SLinus Torvalds #define TICK_SIZE (tick_nsec / 1000)
661da177e4SLinus Torvalds 
671da177e4SLinus Torvalds /*
681da177e4SLinus Torvalds  * Shift amount by which scaled_ticks_per_cycle is scaled.  Shifting
691da177e4SLinus Torvalds  * by 48 gives us 16 bits for HZ while keeping the accuracy good even
701da177e4SLinus Torvalds  * for large CPU clock rates.
711da177e4SLinus Torvalds  */
721da177e4SLinus Torvalds #define FIX_SHIFT	48
731da177e4SLinus Torvalds 
741da177e4SLinus Torvalds /* lump static variables together for more efficient access: */
751da177e4SLinus Torvalds static struct {
761da177e4SLinus Torvalds 	/* cycle counter last time it got invoked */
771da177e4SLinus Torvalds 	__u32 last_time;
781da177e4SLinus Torvalds 	/* ticks/cycle * 2^48 */
791da177e4SLinus Torvalds 	unsigned long scaled_ticks_per_cycle;
801da177e4SLinus Torvalds 	/* partial unused tick */
811da177e4SLinus Torvalds 	unsigned long partial_tick;
821da177e4SLinus Torvalds } state;
831da177e4SLinus Torvalds 
841da177e4SLinus Torvalds unsigned long est_cycle_freq;
851da177e4SLinus Torvalds 
86e360adbeSPeter Zijlstra #ifdef CONFIG_IRQ_WORK
87979f8671SMichael Cree 
88e360adbeSPeter Zijlstra DEFINE_PER_CPU(u8, irq_work_pending);
89979f8671SMichael Cree 
90e360adbeSPeter Zijlstra #define set_irq_work_pending_flag()  __get_cpu_var(irq_work_pending) = 1
91e360adbeSPeter Zijlstra #define test_irq_work_pending()      __get_cpu_var(irq_work_pending)
92e360adbeSPeter Zijlstra #define clear_irq_work_pending()     __get_cpu_var(irq_work_pending) = 0
93979f8671SMichael Cree 
94e360adbeSPeter Zijlstra void set_irq_work_pending(void)
95979f8671SMichael Cree {
96e360adbeSPeter Zijlstra 	set_irq_work_pending_flag();
97979f8671SMichael Cree }
98979f8671SMichael Cree 
99e360adbeSPeter Zijlstra #else  /* CONFIG_IRQ_WORK */
100979f8671SMichael Cree 
101e360adbeSPeter Zijlstra #define test_irq_work_pending()      0
102e360adbeSPeter Zijlstra #define clear_irq_work_pending()
103979f8671SMichael Cree 
104e360adbeSPeter Zijlstra #endif /* CONFIG_IRQ_WORK */
105979f8671SMichael Cree 
1061da177e4SLinus Torvalds 
1071da177e4SLinus Torvalds static inline __u32 rpcc(void)
1081da177e4SLinus Torvalds {
1091da177e4SLinus Torvalds     __u32 result;
1101da177e4SLinus Torvalds     asm volatile ("rpcc %0" : "=r"(result));
1111da177e4SLinus Torvalds     return result;
1121da177e4SLinus Torvalds }
1131da177e4SLinus Torvalds 
1141e871be1SJohn Stultz int update_persistent_clock(struct timespec now)
1151e871be1SJohn Stultz {
1161e871be1SJohn Stultz 	return set_rtc_mmss(now.tv_sec);
1171e871be1SJohn Stultz }
1181e871be1SJohn Stultz 
1191e871be1SJohn Stultz void read_persistent_clock(struct timespec *ts)
1201e871be1SJohn Stultz {
1211e871be1SJohn Stultz 	unsigned int year, mon, day, hour, min, sec, epoch;
1221e871be1SJohn Stultz 
1231e871be1SJohn Stultz 	sec = CMOS_READ(RTC_SECONDS);
1241e871be1SJohn Stultz 	min = CMOS_READ(RTC_MINUTES);
1251e871be1SJohn Stultz 	hour = CMOS_READ(RTC_HOURS);
1261e871be1SJohn Stultz 	day = CMOS_READ(RTC_DAY_OF_MONTH);
1271e871be1SJohn Stultz 	mon = CMOS_READ(RTC_MONTH);
1281e871be1SJohn Stultz 	year = CMOS_READ(RTC_YEAR);
1291e871be1SJohn Stultz 
1301e871be1SJohn Stultz 	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
1311e871be1SJohn Stultz 		sec = bcd2bin(sec);
1321e871be1SJohn Stultz 		min = bcd2bin(min);
1331e871be1SJohn Stultz 		hour = bcd2bin(hour);
1341e871be1SJohn Stultz 		day = bcd2bin(day);
1351e871be1SJohn Stultz 		mon = bcd2bin(mon);
1361e871be1SJohn Stultz 		year = bcd2bin(year);
1371e871be1SJohn Stultz 	}
1381e871be1SJohn Stultz 
1391e871be1SJohn Stultz 	/* PC-like is standard; used for year >= 70 */
1401e871be1SJohn Stultz 	epoch = 1900;
1411e871be1SJohn Stultz 	if (year < 20)
1421e871be1SJohn Stultz 		epoch = 2000;
1431e871be1SJohn Stultz 	else if (year >= 20 && year < 48)
1441e871be1SJohn Stultz 		/* NT epoch */
1451e871be1SJohn Stultz 		epoch = 1980;
1461e871be1SJohn Stultz 	else if (year >= 48 && year < 70)
1471e871be1SJohn Stultz 		/* Digital UNIX epoch */
1481e871be1SJohn Stultz 		epoch = 1952;
1491e871be1SJohn Stultz 
1501e871be1SJohn Stultz 	printk(KERN_INFO "Using epoch = %d\n", epoch);
1511e871be1SJohn Stultz 
1521e871be1SJohn Stultz 	if ((year += epoch) < 1970)
1531e871be1SJohn Stultz 		year += 100;
1541e871be1SJohn Stultz 
1551e871be1SJohn Stultz 	ts->tv_sec = mktime(year, mon, day, hour, min, sec);
1561e871be1SJohn Stultz }
1571e871be1SJohn Stultz 
1581e871be1SJohn Stultz 
1591e871be1SJohn Stultz 
1601da177e4SLinus Torvalds /*
1611da177e4SLinus Torvalds  * timer_interrupt() needs to keep up the real-time clock,
1621da177e4SLinus Torvalds  * as well as call the "do_timer()" routine every clocktick
1631da177e4SLinus Torvalds  */
1648774cb81SAl Viro irqreturn_t timer_interrupt(int irq, void *dev)
1651da177e4SLinus Torvalds {
1661da177e4SLinus Torvalds 	unsigned long delta;
1671da177e4SLinus Torvalds 	__u32 now;
1681da177e4SLinus Torvalds 	long nticks;
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds #ifndef CONFIG_SMP
1711da177e4SLinus Torvalds 	/* Not SMP, do kernel PC profiling here.  */
1728774cb81SAl Viro 	profile_tick(CPU_PROFILING);
1731da177e4SLinus Torvalds #endif
1741da177e4SLinus Torvalds 
1751da177e4SLinus Torvalds 	write_seqlock(&xtime_lock);
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds 	/*
1781da177e4SLinus Torvalds 	 * Calculate how many ticks have passed since the last update,
1791da177e4SLinus Torvalds 	 * including any previous partial leftover.  Save any resulting
1801da177e4SLinus Torvalds 	 * fraction for the next pass.
1811da177e4SLinus Torvalds 	 */
1821da177e4SLinus Torvalds 	now = rpcc();
1831da177e4SLinus Torvalds 	delta = now - state.last_time;
1841da177e4SLinus Torvalds 	state.last_time = now;
1851da177e4SLinus Torvalds 	delta = delta * state.scaled_ticks_per_cycle + state.partial_tick;
1861da177e4SLinus Torvalds 	state.partial_tick = delta & ((1UL << FIX_SHIFT) - 1);
1871da177e4SLinus Torvalds 	nticks = delta >> FIX_SHIFT;
1881da177e4SLinus Torvalds 
189aa02cd2dSPeter Zijlstra 	if (nticks)
190aa02cd2dSPeter Zijlstra 		do_timer(nticks);
1911da177e4SLinus Torvalds 
1921da177e4SLinus Torvalds 	write_sequnlock(&xtime_lock);
193aa02cd2dSPeter Zijlstra 
194e360adbeSPeter Zijlstra 	if (test_irq_work_pending()) {
195e360adbeSPeter Zijlstra 		clear_irq_work_pending();
196e360adbeSPeter Zijlstra 		irq_work_run();
197979f8671SMichael Cree 	}
198979f8671SMichael Cree 
199bdc8b891SMichael Cree #ifndef CONFIG_SMP
200bdc8b891SMichael Cree 	while (nticks--)
201bdc8b891SMichael Cree 		update_process_times(user_mode(get_irq_regs()));
202bdc8b891SMichael Cree #endif
203bdc8b891SMichael Cree 
2041da177e4SLinus Torvalds 	return IRQ_HANDLED;
2051da177e4SLinus Torvalds }
2061da177e4SLinus Torvalds 
207ebaf4fc1SSam Ravnborg void __init
2081da177e4SLinus Torvalds common_init_rtc(void)
2091da177e4SLinus Torvalds {
2101da177e4SLinus Torvalds 	unsigned char x;
2111da177e4SLinus Torvalds 
2121da177e4SLinus Torvalds 	/* Reset periodic interrupt frequency.  */
2131da177e4SLinus Torvalds 	x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f;
2141da177e4SLinus Torvalds         /* Test includes known working values on various platforms
2151da177e4SLinus Torvalds            where 0x26 is wrong; we refuse to change those. */
2161da177e4SLinus Torvalds 	if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) {
2171da177e4SLinus Torvalds 		printk("Setting RTC_FREQ to 1024 Hz (%x)\n", x);
2181da177e4SLinus Torvalds 		CMOS_WRITE(0x26, RTC_FREQ_SELECT);
2191da177e4SLinus Torvalds 	}
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds 	/* Turn on periodic interrupts.  */
2221da177e4SLinus Torvalds 	x = CMOS_READ(RTC_CONTROL);
2231da177e4SLinus Torvalds 	if (!(x & RTC_PIE)) {
2241da177e4SLinus Torvalds 		printk("Turning on RTC interrupts.\n");
2251da177e4SLinus Torvalds 		x |= RTC_PIE;
2261da177e4SLinus Torvalds 		x &= ~(RTC_AIE | RTC_UIE);
2271da177e4SLinus Torvalds 		CMOS_WRITE(x, RTC_CONTROL);
2281da177e4SLinus Torvalds 	}
2291da177e4SLinus Torvalds 	(void) CMOS_READ(RTC_INTR_FLAGS);
2301da177e4SLinus Torvalds 
2311da177e4SLinus Torvalds 	outb(0x36, 0x43);	/* pit counter 0: system timer */
2321da177e4SLinus Torvalds 	outb(0x00, 0x40);
2331da177e4SLinus Torvalds 	outb(0x00, 0x40);
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds 	outb(0xb6, 0x43);	/* pit counter 2: speaker */
2361da177e4SLinus Torvalds 	outb(0x31, 0x42);
2371da177e4SLinus Torvalds 	outb(0x13, 0x42);
2381da177e4SLinus Torvalds 
2391da177e4SLinus Torvalds 	init_rtc_irq();
2401da177e4SLinus Torvalds }
2411da177e4SLinus Torvalds 
2425f7dc5d7SIvan Kokshaysky unsigned int common_get_rtc_time(struct rtc_time *time)
2435f7dc5d7SIvan Kokshaysky {
2445f7dc5d7SIvan Kokshaysky 	return __get_rtc_time(time);
2455f7dc5d7SIvan Kokshaysky }
2465f7dc5d7SIvan Kokshaysky 
2475f7dc5d7SIvan Kokshaysky int common_set_rtc_time(struct rtc_time *time)
2485f7dc5d7SIvan Kokshaysky {
2495f7dc5d7SIvan Kokshaysky 	return __set_rtc_time(time);
2505f7dc5d7SIvan Kokshaysky }
2511da177e4SLinus Torvalds 
2521da177e4SLinus Torvalds /* Validate a computed cycle counter result against the known bounds for
2531da177e4SLinus Torvalds    the given processor core.  There's too much brokenness in the way of
2541da177e4SLinus Torvalds    timing hardware for any one method to work everywhere.  :-(
2551da177e4SLinus Torvalds 
2561da177e4SLinus Torvalds    Return 0 if the result cannot be trusted, otherwise return the argument.  */
2571da177e4SLinus Torvalds 
2581da177e4SLinus Torvalds static unsigned long __init
2591da177e4SLinus Torvalds validate_cc_value(unsigned long cc)
2601da177e4SLinus Torvalds {
2611da177e4SLinus Torvalds 	static struct bounds {
2621da177e4SLinus Torvalds 		unsigned int min, max;
2631da177e4SLinus Torvalds 	} cpu_hz[] __initdata = {
2641da177e4SLinus Torvalds 		[EV3_CPU]    = {   50000000,  200000000 },	/* guess */
2651da177e4SLinus Torvalds 		[EV4_CPU]    = {  100000000,  300000000 },
2661da177e4SLinus Torvalds 		[LCA4_CPU]   = {  100000000,  300000000 },	/* guess */
2671da177e4SLinus Torvalds 		[EV45_CPU]   = {  200000000,  300000000 },
2681da177e4SLinus Torvalds 		[EV5_CPU]    = {  250000000,  433000000 },
2691da177e4SLinus Torvalds 		[EV56_CPU]   = {  333000000,  667000000 },
2701da177e4SLinus Torvalds 		[PCA56_CPU]  = {  400000000,  600000000 },	/* guess */
2711da177e4SLinus Torvalds 		[PCA57_CPU]  = {  500000000,  600000000 },	/* guess */
2721da177e4SLinus Torvalds 		[EV6_CPU]    = {  466000000,  600000000 },
2731da177e4SLinus Torvalds 		[EV67_CPU]   = {  600000000,  750000000 },
2741da177e4SLinus Torvalds 		[EV68AL_CPU] = {  750000000,  940000000 },
2751da177e4SLinus Torvalds 		[EV68CB_CPU] = { 1000000000, 1333333333 },
2761da177e4SLinus Torvalds 		/* None of the following are shipping as of 2001-11-01.  */
2771da177e4SLinus Torvalds 		[EV68CX_CPU] = { 1000000000, 1700000000 },	/* guess */
2781da177e4SLinus Torvalds 		[EV69_CPU]   = { 1000000000, 1700000000 },	/* guess */
2791da177e4SLinus Torvalds 		[EV7_CPU]    = {  800000000, 1400000000 },	/* guess */
2801da177e4SLinus Torvalds 		[EV79_CPU]   = { 1000000000, 2000000000 },	/* guess */
2811da177e4SLinus Torvalds 	};
2821da177e4SLinus Torvalds 
2831da177e4SLinus Torvalds 	/* Allow for some drift in the crystal.  10MHz is more than enough.  */
2841da177e4SLinus Torvalds 	const unsigned int deviation = 10000000;
2851da177e4SLinus Torvalds 
2861da177e4SLinus Torvalds 	struct percpu_struct *cpu;
2871da177e4SLinus Torvalds 	unsigned int index;
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds 	cpu = (struct percpu_struct *)((char*)hwrpb + hwrpb->processor_offset);
2901da177e4SLinus Torvalds 	index = cpu->type & 0xffffffff;
2911da177e4SLinus Torvalds 
2921da177e4SLinus Torvalds 	/* If index out of bounds, no way to validate.  */
29325c8716cSTobias Klauser 	if (index >= ARRAY_SIZE(cpu_hz))
2941da177e4SLinus Torvalds 		return cc;
2951da177e4SLinus Torvalds 
2961da177e4SLinus Torvalds 	/* If index contains no data, no way to validate.  */
2971da177e4SLinus Torvalds 	if (cpu_hz[index].max == 0)
2981da177e4SLinus Torvalds 		return cc;
2991da177e4SLinus Torvalds 
3001da177e4SLinus Torvalds 	if (cc < cpu_hz[index].min - deviation
3011da177e4SLinus Torvalds 	    || cc > cpu_hz[index].max + deviation)
3021da177e4SLinus Torvalds 		return 0;
3031da177e4SLinus Torvalds 
3041da177e4SLinus Torvalds 	return cc;
3051da177e4SLinus Torvalds }
3061da177e4SLinus Torvalds 
3071da177e4SLinus Torvalds 
3081da177e4SLinus Torvalds /*
3091da177e4SLinus Torvalds  * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from
3101da177e4SLinus Torvalds  * arch/i386/time.c.
3111da177e4SLinus Torvalds  */
3121da177e4SLinus Torvalds 
3131da177e4SLinus Torvalds #define CALIBRATE_LATCH	0xffff
3141da177e4SLinus Torvalds #define TIMEOUT_COUNT	0x100000
3151da177e4SLinus Torvalds 
3161da177e4SLinus Torvalds static unsigned long __init
3171da177e4SLinus Torvalds calibrate_cc_with_pit(void)
3181da177e4SLinus Torvalds {
3191da177e4SLinus Torvalds 	int cc, count = 0;
3201da177e4SLinus Torvalds 
3211da177e4SLinus Torvalds 	/* Set the Gate high, disable speaker */
3221da177e4SLinus Torvalds 	outb((inb(0x61) & ~0x02) | 0x01, 0x61);
3231da177e4SLinus Torvalds 
3241da177e4SLinus Torvalds 	/*
3251da177e4SLinus Torvalds 	 * Now let's take care of CTC channel 2
3261da177e4SLinus Torvalds 	 *
3271da177e4SLinus Torvalds 	 * Set the Gate high, program CTC channel 2 for mode 0,
3281da177e4SLinus Torvalds 	 * (interrupt on terminal count mode), binary count,
3291da177e4SLinus Torvalds 	 * load 5 * LATCH count, (LSB and MSB) to begin countdown.
3301da177e4SLinus Torvalds 	 */
3311da177e4SLinus Torvalds 	outb(0xb0, 0x43);		/* binary, mode 0, LSB/MSB, Ch 2 */
3321da177e4SLinus Torvalds 	outb(CALIBRATE_LATCH & 0xff, 0x42);	/* LSB of count */
3331da177e4SLinus Torvalds 	outb(CALIBRATE_LATCH >> 8, 0x42);	/* MSB of count */
3341da177e4SLinus Torvalds 
3351da177e4SLinus Torvalds 	cc = rpcc();
3361da177e4SLinus Torvalds 	do {
3371da177e4SLinus Torvalds 		count++;
3381da177e4SLinus Torvalds 	} while ((inb(0x61) & 0x20) == 0 && count < TIMEOUT_COUNT);
3391da177e4SLinus Torvalds 	cc = rpcc() - cc;
3401da177e4SLinus Torvalds 
3411da177e4SLinus Torvalds 	/* Error: ECTCNEVERSET or ECPUTOOFAST.  */
3421da177e4SLinus Torvalds 	if (count <= 1 || count == TIMEOUT_COUNT)
3431da177e4SLinus Torvalds 		return 0;
3441da177e4SLinus Torvalds 
3451da177e4SLinus Torvalds 	return ((long)cc * PIT_TICK_RATE) / (CALIBRATE_LATCH + 1);
3461da177e4SLinus Torvalds }
3471da177e4SLinus Torvalds 
3481da177e4SLinus Torvalds /* The Linux interpretation of the CMOS clock register contents:
3491da177e4SLinus Torvalds    When the Update-In-Progress (UIP) flag goes from 1 to 0, the
3501da177e4SLinus Torvalds    RTC registers show the second which has precisely just started.
3511da177e4SLinus Torvalds    Let's hope other operating systems interpret the RTC the same way.  */
3521da177e4SLinus Torvalds 
3531da177e4SLinus Torvalds static unsigned long __init
3541da177e4SLinus Torvalds rpcc_after_update_in_progress(void)
3551da177e4SLinus Torvalds {
3561da177e4SLinus Torvalds 	do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP));
3571da177e4SLinus Torvalds 	do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP);
3581da177e4SLinus Torvalds 
3591da177e4SLinus Torvalds 	return rpcc();
3601da177e4SLinus Torvalds }
3611da177e4SLinus Torvalds 
3629ce34c8fSJohn Stultz #ifndef CONFIG_SMP
3639ce34c8fSJohn Stultz /* Until and unless we figure out how to get cpu cycle counters
3649ce34c8fSJohn Stultz    in sync and keep them there, we can't use the rpcc.  */
3659ce34c8fSJohn Stultz static cycle_t read_rpcc(struct clocksource *cs)
3669ce34c8fSJohn Stultz {
3679ce34c8fSJohn Stultz 	cycle_t ret = (cycle_t)rpcc();
3689ce34c8fSJohn Stultz 	return ret;
3699ce34c8fSJohn Stultz }
3709ce34c8fSJohn Stultz 
3719ce34c8fSJohn Stultz static struct clocksource clocksource_rpcc = {
3729ce34c8fSJohn Stultz 	.name                   = "rpcc",
3739ce34c8fSJohn Stultz 	.rating                 = 300,
3749ce34c8fSJohn Stultz 	.read                   = read_rpcc,
3759ce34c8fSJohn Stultz 	.mask                   = CLOCKSOURCE_MASK(32),
3769ce34c8fSJohn Stultz 	.flags                  = CLOCK_SOURCE_IS_CONTINUOUS
3779ce34c8fSJohn Stultz };
3789ce34c8fSJohn Stultz 
3799ce34c8fSJohn Stultz static inline void register_rpcc_clocksource(long cycle_freq)
3809ce34c8fSJohn Stultz {
3819ce34c8fSJohn Stultz 	clocksource_calc_mult_shift(&clocksource_rpcc, cycle_freq, 4);
3829ce34c8fSJohn Stultz 	clocksource_register(&clocksource_rpcc);
3839ce34c8fSJohn Stultz }
3849ce34c8fSJohn Stultz #else /* !CONFIG_SMP */
3859ce34c8fSJohn Stultz static inline void register_rpcc_clocksource(long cycle_freq)
3869ce34c8fSJohn Stultz {
3879ce34c8fSJohn Stultz }
3889ce34c8fSJohn Stultz #endif /* !CONFIG_SMP */
3899ce34c8fSJohn Stultz 
3901da177e4SLinus Torvalds void __init
3911da177e4SLinus Torvalds time_init(void)
3921da177e4SLinus Torvalds {
3931e871be1SJohn Stultz 	unsigned int cc1, cc2;
3941da177e4SLinus Torvalds 	unsigned long cycle_freq, tolerance;
3951da177e4SLinus Torvalds 	long diff;
3961da177e4SLinus Torvalds 
3971da177e4SLinus Torvalds 	/* Calibrate CPU clock -- attempt #1.  */
3981da177e4SLinus Torvalds 	if (!est_cycle_freq)
3991da177e4SLinus Torvalds 		est_cycle_freq = validate_cc_value(calibrate_cc_with_pit());
4001da177e4SLinus Torvalds 
4014c2e6f6aSMatt Mackall 	cc1 = rpcc();
4021da177e4SLinus Torvalds 
4031da177e4SLinus Torvalds 	/* Calibrate CPU clock -- attempt #2.  */
4041da177e4SLinus Torvalds 	if (!est_cycle_freq) {
4054c2e6f6aSMatt Mackall 		cc1 = rpcc_after_update_in_progress();
4061da177e4SLinus Torvalds 		cc2 = rpcc_after_update_in_progress();
4071da177e4SLinus Torvalds 		est_cycle_freq = validate_cc_value(cc2 - cc1);
4081da177e4SLinus Torvalds 		cc1 = cc2;
4091da177e4SLinus Torvalds 	}
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds 	cycle_freq = hwrpb->cycle_freq;
4121da177e4SLinus Torvalds 	if (est_cycle_freq) {
4131da177e4SLinus Torvalds 		/* If the given value is within 250 PPM of what we calculated,
4141da177e4SLinus Torvalds 		   accept it.  Otherwise, use what we found.  */
4151da177e4SLinus Torvalds 		tolerance = cycle_freq / 4000;
4161da177e4SLinus Torvalds 		diff = cycle_freq - est_cycle_freq;
4171da177e4SLinus Torvalds 		if (diff < 0)
4181da177e4SLinus Torvalds 			diff = -diff;
4191da177e4SLinus Torvalds 		if ((unsigned long)diff > tolerance) {
4201da177e4SLinus Torvalds 			cycle_freq = est_cycle_freq;
4211da177e4SLinus Torvalds 			printk("HWRPB cycle frequency bogus.  "
4221da177e4SLinus Torvalds 			       "Estimated %lu Hz\n", cycle_freq);
4231da177e4SLinus Torvalds 		} else {
4241da177e4SLinus Torvalds 			est_cycle_freq = 0;
4251da177e4SLinus Torvalds 		}
4261da177e4SLinus Torvalds 	} else if (! validate_cc_value (cycle_freq)) {
4271da177e4SLinus Torvalds 		printk("HWRPB cycle frequency bogus, "
4281da177e4SLinus Torvalds 		       "and unable to estimate a proper value!\n");
4291da177e4SLinus Torvalds 	}
4301da177e4SLinus Torvalds 
4311da177e4SLinus Torvalds 	/* From John Bowman <bowman@math.ualberta.ca>: allow the values
4321da177e4SLinus Torvalds 	   to settle, as the Update-In-Progress bit going low isn't good
4331da177e4SLinus Torvalds 	   enough on some hardware.  2ms is our guess; we haven't found
4341da177e4SLinus Torvalds 	   bogomips yet, but this is close on a 500Mhz box.  */
4351da177e4SLinus Torvalds 	__delay(1000000);
4361da177e4SLinus Torvalds 
4371da177e4SLinus Torvalds 
4381da177e4SLinus Torvalds 	if (HZ > (1<<16)) {
4391da177e4SLinus Torvalds 		extern void __you_loose (void);
4401da177e4SLinus Torvalds 		__you_loose();
4411da177e4SLinus Torvalds 	}
4421da177e4SLinus Torvalds 
4439ce34c8fSJohn Stultz 	register_rpcc_clocksource(cycle_freq);
4449ce34c8fSJohn Stultz 
4451da177e4SLinus Torvalds 	state.last_time = cc1;
4461da177e4SLinus Torvalds 	state.scaled_ticks_per_cycle
4471da177e4SLinus Torvalds 		= ((unsigned long) HZ << FIX_SHIFT) / cycle_freq;
4481da177e4SLinus Torvalds 	state.partial_tick = 0L;
4491da177e4SLinus Torvalds 
4501da177e4SLinus Torvalds 	/* Startup the timer source. */
4511da177e4SLinus Torvalds 	alpha_mv.init_rtc();
4521da177e4SLinus Torvalds }
4531da177e4SLinus Torvalds 
4541da177e4SLinus Torvalds /*
4551da177e4SLinus Torvalds  * In order to set the CMOS clock precisely, set_rtc_mmss has to be
4561da177e4SLinus Torvalds  * called 500 ms after the second nowtime has started, because when
4571da177e4SLinus Torvalds  * nowtime is written into the registers of the CMOS clock, it will
4581da177e4SLinus Torvalds  * jump to the next second precisely 500 ms later. Check the Motorola
4591da177e4SLinus Torvalds  * MC146818A or Dallas DS12887 data sheet for details.
4601da177e4SLinus Torvalds  *
4611da177e4SLinus Torvalds  * BUG: This routine does not handle hour overflow properly; it just
4621da177e4SLinus Torvalds  *      sets the minutes. Usually you won't notice until after reboot!
4631da177e4SLinus Torvalds  */
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds 
4661da177e4SLinus Torvalds static int
4671da177e4SLinus Torvalds set_rtc_mmss(unsigned long nowtime)
4681da177e4SLinus Torvalds {
4691da177e4SLinus Torvalds 	int retval = 0;
4701da177e4SLinus Torvalds 	int real_seconds, real_minutes, cmos_minutes;
4711da177e4SLinus Torvalds 	unsigned char save_control, save_freq_select;
4721da177e4SLinus Torvalds 
4731da177e4SLinus Torvalds 	/* irq are locally disabled here */
4741da177e4SLinus Torvalds 	spin_lock(&rtc_lock);
4751da177e4SLinus Torvalds 	/* Tell the clock it's being set */
4761da177e4SLinus Torvalds 	save_control = CMOS_READ(RTC_CONTROL);
4771da177e4SLinus Torvalds 	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
4781da177e4SLinus Torvalds 
4791da177e4SLinus Torvalds 	/* Stop and reset prescaler */
4801da177e4SLinus Torvalds 	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
4811da177e4SLinus Torvalds 	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
4821da177e4SLinus Torvalds 
4831da177e4SLinus Torvalds 	cmos_minutes = CMOS_READ(RTC_MINUTES);
4841da177e4SLinus Torvalds 	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
48518b1bd05SAdrian Bunk 		cmos_minutes = bcd2bin(cmos_minutes);
4861da177e4SLinus Torvalds 
4871da177e4SLinus Torvalds 	/*
4881da177e4SLinus Torvalds 	 * since we're only adjusting minutes and seconds,
4891da177e4SLinus Torvalds 	 * don't interfere with hour overflow. This avoids
4901da177e4SLinus Torvalds 	 * messing with unknown time zones but requires your
4911da177e4SLinus Torvalds 	 * RTC not to be off by more than 15 minutes
4921da177e4SLinus Torvalds 	 */
4931da177e4SLinus Torvalds 	real_seconds = nowtime % 60;
4941da177e4SLinus Torvalds 	real_minutes = nowtime / 60;
4951da177e4SLinus Torvalds 	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) {
4961da177e4SLinus Torvalds 		/* correct for half hour time zone */
4971da177e4SLinus Torvalds 		real_minutes += 30;
4981da177e4SLinus Torvalds 	}
4991da177e4SLinus Torvalds 	real_minutes %= 60;
5001da177e4SLinus Torvalds 
5011da177e4SLinus Torvalds 	if (abs(real_minutes - cmos_minutes) < 30) {
5021da177e4SLinus Torvalds 		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
50318b1bd05SAdrian Bunk 			real_seconds = bin2bcd(real_seconds);
50418b1bd05SAdrian Bunk 			real_minutes = bin2bcd(real_minutes);
5051da177e4SLinus Torvalds 		}
5061da177e4SLinus Torvalds 		CMOS_WRITE(real_seconds,RTC_SECONDS);
5071da177e4SLinus Torvalds 		CMOS_WRITE(real_minutes,RTC_MINUTES);
5081da177e4SLinus Torvalds 	} else {
5093e5c1240SStephen Hemminger 		printk_once(KERN_NOTICE
5101da177e4SLinus Torvalds 		       "set_rtc_mmss: can't update from %d to %d\n",
5111da177e4SLinus Torvalds 		       cmos_minutes, real_minutes);
5121da177e4SLinus Torvalds  		retval = -1;
5131da177e4SLinus Torvalds 	}
5141da177e4SLinus Torvalds 
5151da177e4SLinus Torvalds 	/* The following flags have to be released exactly in this order,
5161da177e4SLinus Torvalds 	 * otherwise the DS12887 (popular MC146818A clone with integrated
5171da177e4SLinus Torvalds 	 * battery and quartz) will not reset the oscillator and will not
5181da177e4SLinus Torvalds 	 * update precisely 500 ms later. You won't find this mentioned in
5191da177e4SLinus Torvalds 	 * the Dallas Semiconductor data sheets, but who believes data
5201da177e4SLinus Torvalds 	 * sheets anyway ...                           -- Markus Kuhn
5211da177e4SLinus Torvalds 	 */
5221da177e4SLinus Torvalds 	CMOS_WRITE(save_control, RTC_CONTROL);
5231da177e4SLinus Torvalds 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
5241da177e4SLinus Torvalds 	spin_unlock(&rtc_lock);
5251da177e4SLinus Torvalds 
5261da177e4SLinus Torvalds 	return retval;
5271da177e4SLinus Torvalds }
528