2.2.0-final
[davej-history.git] / arch / arm / kernel / time.c
blob22c3639dad8743c6bd819d87327c169e5582d2e8
1 /*
2 * linux/arch/arm/kernel/time.c
4 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
5 * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King
7 * This file contains the ARM-specific time handling details:
8 * reading the RTC at bootup, etc...
10 * 1994-07-02 Alan Modra
11 * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
12 * 1998-12-20 Updated NTP code according to technical memorandum Jan '96
13 * "A Kernel Model for Precision Timekeeping" by Dave Mills
15 #include <linux/errno.h>
16 #include <linux/sched.h>
17 #include <linux/kernel.h>
18 #include <linux/param.h>
19 #include <linux/string.h>
20 #include <linux/mm.h>
21 #include <linux/interrupt.h>
22 #include <linux/time.h>
23 #include <linux/delay.h>
24 #include <linux/init.h>
25 #include <linux/smp.h>
26 #include <linux/init.h>
27 #include <linux/delay.h>
29 #include <asm/uaccess.h>
30 #include <asm/io.h>
31 #include <asm/irq.h>
33 #include <linux/timex.h>
34 #include <asm/hardware.h>
36 extern int setup_arm_irq(int, struct irqaction *);
37 extern volatile unsigned long lost_ticks;
39 /* change this if you have some constant time drift */
40 #define USECS_PER_JIFFY (1000000/HZ)
42 #ifndef BCD_TO_BIN
43 #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
44 #endif
46 #ifndef BIN_TO_BCD
47 #define BIN_TO_BCD(val) ((val)=(((val)/10)<<4) + (val)%10)
48 #endif
50 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
51 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
52 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
54 * [For the Julian calendar (which was used in Russia before 1917,
55 * Britain & colonies before 1752, anywhere else before 1582,
56 * and is still in use by some communities) leave out the
57 * -year/100+year/400 terms, and add 10.]
59 * This algorithm was first published by Gauss (I think).
61 * WARNING: this function will overflow on 2106-02-07 06:28:16 on
62 * machines were long is 32-bit! (However, as time_t is signed, we
63 * will already get problems at other places on 2038-01-19 03:14:08)
65 unsigned long mktime(unsigned int year, unsigned int mon,
66 unsigned int day, unsigned int hour,
67 unsigned int min, unsigned int sec)
69 if (0 >= (int) (mon -= 2)) { /* 1..12 -> 11,12,1..10 */
70 mon += 12; /* Puts Feb last since it has leap day */
71 year -= 1;
73 return (((
74 (unsigned long)(year/4 - year/100 + year/400 + 367*mon/12 + day) +
75 year*365 - 719499
76 )*24 + hour /* now have hours */
77 )*60 + min /* now have minutes */
78 )*60 + sec; /* finally seconds */
81 #include <asm/arch/time.h>
83 static unsigned long do_gettimeoffset(void)
85 return gettimeoffset ();
88 void do_gettimeofday(struct timeval *tv)
90 unsigned long flags;
92 save_flags_cli (flags);
93 *tv = xtime;
94 tv->tv_usec += do_gettimeoffset();
97 * xtime is atomically updated in timer_bh. lost_ticks is
98 * nonzero if the tiemr bottom half hasnt executed yet.
100 if (lost_ticks)
101 tv->tv_usec += USECS_PER_JIFFY;
103 restore_flags(flags);
105 if (tv->tv_usec >= 1000000) {
106 tv->tv_usec -= 1000000;
107 tv->tv_sec++;
111 void do_settimeofday(struct timeval *tv)
113 cli ();
114 /* This is revolting. We need to set the xtime.tv_usec
115 * correctly. However, the value in this location is
116 * is value at the last tick.
117 * Discover what correction gettimeofday
118 * would have done, and then undo it!
120 tv->tv_usec -= do_gettimeoffset();
122 if (tv->tv_usec < 0) {
123 tv->tv_usec += 1000000;
124 tv->tv_sec--;
127 xtime = *tv;
128 time_adjust = 0; /* stop active adjtime() */
129 time_status |= STA_UNSYNC;
130 time_state = TIME_ERROR; /* p. 24, (a) */
131 time_maxerror = NTP_PHASE_LIMIT;
132 time_esterror = NTP_PHASE_LIMIT;
133 sti ();
137 * timer_interrupt() needs to keep up the real-time clock,
138 * as well as call the "do_timer()" routine every clocktick.
140 static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
142 if (reset_timer ())
143 do_timer(regs);
145 update_rtc ();
148 static struct irqaction irqtimer = { timer_interrupt, 0, 0, "timer", NULL, NULL};
150 __initfunc(void time_init(void))
152 xtime.tv_sec = setup_timer();
153 xtime.tv_usec = 0;
155 setup_arm_irq(IRQ_TIMER, &irqtimer);