Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[pandora-kernel.git] / arch / arm26 / kernel / time.c
1 /*
2  *  linux/arch/arm26/kernel/time.c
3  *
4  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
5  *  Modifications for ARM (C) 1994-2001 Russell King
6  *  Mods for ARM26 (C) 2003 Ian Molton
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  *
12  *  This file contains the ARM-specific time handling details:
13  *  reading the RTC at bootup, etc...
14  *
15  *  1994-07-02  Alan Modra
16  *              fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
17  *  1998-12-20  Updated NTP code according to technical memorandum Jan '96
18  *              "A Kernel Model for Precision Timekeeping" by Dave Mills
19  */
20
21 #include <linux/module.h>
22 #include <linux/kernel.h>
23 #include <linux/interrupt.h>
24 #include <linux/time.h>
25 #include <linux/init.h>
26 #include <linux/smp.h>
27 #include <linux/timex.h>
28 #include <linux/errno.h>
29 #include <linux/profile.h>
30
31 #include <asm/hardware.h>
32 #include <asm/io.h>
33 #include <asm/irq.h>
34 #include <asm/ioc.h>
35
36 extern unsigned long wall_jiffies;
37
38 /* this needs a better home */
39 DEFINE_SPINLOCK(rtc_lock);
40
41 /* change this if you have some constant time drift */
42 #define USECS_PER_JIFFY (1000000/HZ)
43
44 static int dummy_set_rtc(void)
45 {
46         return 0;
47 }
48
49 /*
50  * hook for setting the RTC's idea of the current time.
51  */
52 int (*set_rtc)(void) = dummy_set_rtc;
53
54 /*
55  * Get time offset based on IOCs timer.
56  * FIXME - if this is called with interrutps off, why the shennanigans
57  * below ?
58  */
59 static unsigned long gettimeoffset(void)
60 {
61         unsigned int count1, count2, status;
62         long offset;
63
64         ioc_writeb (0, IOC_T0LATCH);
65         barrier ();
66         count1 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
67         barrier ();
68         status = ioc_readb(IOC_IRQREQA);
69         barrier ();
70         ioc_writeb (0, IOC_T0LATCH);
71         barrier ();
72         count2 = ioc_readb(IOC_T0CNTL) | (ioc_readb(IOC_T0CNTH) << 8);
73
74         offset = count2;
75         if (count2 < count1) {
76                 /*
77                  * We have not had an interrupt between reading count1
78                  * and count2.
79                  */
80                 if (status & (1 << 5))
81                         offset -= LATCH;
82         } else if (count2 > count1) {
83                 /*
84                  * We have just had another interrupt between reading
85                  * count1 and count2.
86                  */
87                 offset -= LATCH;
88         }
89
90         offset = (LATCH - offset) * (tick_nsec / 1000);
91         return (offset + LATCH/2) / LATCH;
92 }
93
94 /*
95  * Scheduler clock - returns current time in nanosec units.
96  */
97 unsigned long long sched_clock(void)
98 {
99         return (unsigned long long)jiffies * (1000000000 / HZ);
100 }
101
102 static unsigned long next_rtc_update;
103
104 /*
105  * If we have an externally synchronized linux clock, then update
106  * CMOS clock accordingly every ~11 minutes.  set_rtc() has to be
107  * called as close as possible to 500 ms before the new second
108  * starts.
109  */
110 static inline void do_set_rtc(void)
111 {
112         if (!ntp_synced() || set_rtc == NULL)
113                 return;
114
115 //FIXME - timespec.tv_sec is a time_t not unsigned long
116         if (next_rtc_update &&
117             time_before((unsigned long)xtime.tv_sec, next_rtc_update))
118                 return;
119
120         if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) &&
121             xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1))
122                 return;
123
124         if (set_rtc())
125                 /*
126                  * rtc update failed.  Try again in 60s
127                  */
128                 next_rtc_update = xtime.tv_sec + 60;
129         else
130                 next_rtc_update = xtime.tv_sec + 660;
131 }
132
133 #define do_leds()
134
135 void do_gettimeofday(struct timeval *tv)
136 {
137         unsigned long flags;
138         unsigned long seq;
139         unsigned long usec, sec, lost;
140
141         do {
142                 seq = read_seqbegin_irqsave(&xtime_lock, flags);
143                 usec = gettimeoffset();
144
145                 lost = jiffies - wall_jiffies;
146                 if (lost)
147                         usec += lost * USECS_PER_JIFFY;
148
149                 sec = xtime.tv_sec;
150                 usec += xtime.tv_nsec / 1000;
151         } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
152
153         /* usec may have gone up a lot: be safe */
154         while (usec >= 1000000) {
155                 usec -= 1000000;
156                 sec++;
157         }
158
159         tv->tv_sec = sec;
160         tv->tv_usec = usec;
161 }
162
163 EXPORT_SYMBOL(do_gettimeofday);
164
165 int do_settimeofday(struct timespec *tv)
166 {
167         if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
168                 return -EINVAL;
169
170         write_seqlock_irq(&xtime_lock);
171         /*
172          * This is revolting. We need to set "xtime" correctly. However, the
173          * value in this location is the value at the most recent update of
174          * wall time.  Discover what correction gettimeofday() would have
175          * done, and then undo it!
176          */
177         tv->tv_nsec -= 1000 * (gettimeoffset() +
178                         (jiffies - wall_jiffies) * USECS_PER_JIFFY);
179
180         while (tv->tv_nsec < 0) {
181                 tv->tv_nsec += NSEC_PER_SEC;
182                 tv->tv_sec--;
183         }
184
185         xtime.tv_sec = tv->tv_sec;
186         xtime.tv_nsec = tv->tv_nsec;
187         ntp_clear();
188         write_sequnlock_irq(&xtime_lock);
189         clock_was_set();
190         return 0;
191 }
192
193 EXPORT_SYMBOL(do_settimeofday);
194
195 static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
196 {
197         do_timer(regs);
198 #ifndef CONFIG_SMP
199         update_process_times(user_mode(regs));
200 #endif
201         do_set_rtc(); //FIME - EVERY timer IRQ?
202         profile_tick(CPU_PROFILING, regs);
203         return IRQ_HANDLED; //FIXME - is this right?
204 }
205
206 static struct irqaction timer_irq = {
207         .name   = "timer",
208         .flags  = IRQF_DISABLED,
209         .handler = timer_interrupt,
210 };
211
212 extern void ioctime_init(void);
213
214 /*
215  * Set up timer interrupt.
216  */
217 void __init time_init(void)
218 {
219         ioc_writeb(LATCH & 255, IOC_T0LTCHL);
220         ioc_writeb(LATCH >> 8, IOC_T0LTCHH);
221         ioc_writeb(0, IOC_T0GO);
222
223
224         setup_irq(IRQ_TIMER, &timer_irq);
225 }
226