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