http://downloads.netgear.com/files/GPL/GPL_Source_V361j_DM111PSP_series_consumer_rele...
[bcm963xx.git] / kernel / linux / arch / arm / kernel / time.c
1 /*
2  *  linux/arch/arm/kernel/time.c
3  *
4  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
5  *  Modifications for ARM (C) 1994-2001 Russell King
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  *
11  *  This file contains the ARM-specific time handling details:
12  *  reading the RTC at bootup, etc...
13  *
14  *  1994-07-02  Alan Modra
15  *              fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
16  *  1998-12-20  Updated NTP code according to technical memorandum Jan '96
17  *              "A Kernel Model for Precision Timekeeping" by Dave Mills
18  */
19 #include <linux/config.h>
20 #include <linux/module.h>
21 #include <linux/kernel.h>
22 #include <linux/interrupt.h>
23 #include <linux/time.h>
24 #include <linux/init.h>
25 #include <linux/smp.h>
26 #include <linux/timex.h>
27 #include <linux/errno.h>
28 #include <linux/profile.h>
29 #include <linux/sysdev.h>
30 #include <linux/timer.h>
31
32 #include <asm/hardware.h>
33 #include <asm/io.h>
34 #include <asm/irq.h>
35 #include <asm/leds.h>
36
37 #include <asm/mach/time.h>
38
39 u64 jiffies_64 = INITIAL_JIFFIES;
40
41 EXPORT_SYMBOL(jiffies_64);
42
43 extern unsigned long wall_jiffies;
44
45 /* this needs a better home */
46 spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
47
48 #ifdef CONFIG_SA1100_RTC_MODULE
49 EXPORT_SYMBOL(rtc_lock);
50 #endif
51
52 /* change this if you have some constant time drift */
53 #define USECS_PER_JIFFY (1000000/HZ)
54
55
56 /*
57  * hook for setting the RTC's idea of the current time.
58  */
59 int (*set_rtc)(void);
60
61 static unsigned long dummy_gettimeoffset(void)
62 {
63         return 0;
64 }
65
66 /*
67  * hook for getting the time offset.  Note that it is
68  * always called with interrupts disabled.
69  */
70 unsigned long (*gettimeoffset)(void) = dummy_gettimeoffset;
71
72 /*
73  * Scheduler clock - returns current time in nanosec units.
74  * This is the default implementation.  Sub-architecture
75  * implementations can override this.
76  */
77 unsigned long long __attribute__((weak)) sched_clock(void)
78 {
79         return (unsigned long long)jiffies * (1000000000 / HZ);
80 }
81
82 /*
83  * Handle kernel profile stuff...
84  */
85 static inline void do_profile(struct pt_regs *regs)
86 {
87
88         profile_hook(regs);
89
90         if (!user_mode(regs) &&
91             prof_buffer &&
92             current->pid) {
93                 unsigned long pc = instruction_pointer(regs);
94                 extern int _stext;
95
96                 pc -= (unsigned long)&_stext;
97
98                 pc >>= prof_shift;
99
100                 if (pc >= prof_len)
101                         pc = prof_len - 1;
102
103                 prof_buffer[pc] += 1;
104         }
105 }
106
107 static unsigned long next_rtc_update;
108
109 /*
110  * If we have an externally synchronized linux clock, then update
111  * CMOS clock accordingly every ~11 minutes.  set_rtc() has to be
112  * called as close as possible to 500 ms before the new second
113  * starts.
114  */
115 static inline void do_set_rtc(void)
116 {
117         if (time_status & STA_UNSYNC || set_rtc == NULL)
118                 return;
119
120         if (next_rtc_update &&
121             time_before((unsigned long)xtime.tv_sec, next_rtc_update))
122                 return;
123
124         if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) &&
125             xtime.tv_nsec >= 500000000 + ((unsigned) tick_nsec >> 1))
126                 return;
127
128         if (set_rtc())
129                 /*
130                  * rtc update failed.  Try again in 60s
131                  */
132                 next_rtc_update = xtime.tv_sec + 60;
133         else
134                 next_rtc_update = xtime.tv_sec + 660;
135 }
136
137 #ifdef CONFIG_LEDS
138
139 static void dummy_leds_event(led_event_t evt)
140 {
141 }
142
143 void (*leds_event)(led_event_t) = dummy_leds_event;
144
145 struct leds_evt_name {
146         const char      name[8];
147         int             on;
148         int             off;
149 };
150
151 static const struct leds_evt_name evt_names[] = {
152         { "amber", led_amber_on, led_amber_off },
153         { "blue",  led_blue_on,  led_blue_off  },
154         { "green", led_green_on, led_green_off },
155         { "red",   led_red_on,   led_red_off   },
156 };
157
158 static ssize_t leds_store(struct sys_device *dev, const char *buf, size_t size)
159 {
160         int ret = -EINVAL, len = strcspn(buf, " ");
161
162         if (len > 0 && buf[len] == '\0')
163                 len--;
164
165         if (strncmp(buf, "claim", len) == 0) {
166                 leds_event(led_claim);
167                 ret = size;
168         } else if (strncmp(buf, "release", len) == 0) {
169                 leds_event(led_release);
170                 ret = size;
171         } else {
172                 int i;
173
174                 for (i = 0; i < ARRAY_SIZE(evt_names); i++) {
175                         if (strlen(evt_names[i].name) != len ||
176                             strncmp(buf, evt_names[i].name, len) != 0)
177                                 continue;
178                         if (strncmp(buf+len, " on", 3) == 0) {
179                                 leds_event(evt_names[i].on);
180                                 ret = size;
181                         } else if (strncmp(buf+len, " off", 4) == 0) {
182                                 leds_event(evt_names[i].off);
183                                 ret = size;
184                         }
185                         break;
186                 }
187         }
188         return ret;
189 }
190
191 static SYSDEV_ATTR(event, 0200, NULL, leds_store);
192
193 static int leds_suspend(struct sys_device *dev, u32 state)
194 {
195         leds_event(led_stop);
196         return 0;
197 }
198
199 static int leds_resume(struct sys_device *dev)
200 {
201         leds_event(led_start);
202         return 0;
203 }
204
205 static int leds_shutdown(struct sys_device *dev)
206 {
207         leds_event(led_halted);
208         return 0;
209 }
210
211 static struct sysdev_class leds_sysclass = {
212         set_kset_name("leds"),
213         .shutdown       = leds_shutdown,
214         .suspend        = leds_suspend,
215         .resume         = leds_resume,
216 };
217
218 static struct sys_device leds_device = {
219         .id             = 0,
220         .cls            = &leds_sysclass,
221 };
222
223 static int __init leds_init(void)
224 {
225         int ret;
226         ret = sysdev_class_register(&leds_sysclass);
227         if (ret == 0)
228                 ret = sysdev_register(&leds_device);
229         if (ret == 0)
230                 ret = sysdev_create_file(&leds_device, &attr_event);
231         return ret;
232 }
233
234 device_initcall(leds_init);
235
236 EXPORT_SYMBOL(leds_event);
237 #endif
238
239 #ifdef CONFIG_LEDS_TIMER
240 static inline void do_leds(void)
241 {
242         static unsigned int count = 50;
243
244         if (--count == 0) {
245                 count = 50;
246                 leds_event(led_timer);
247         }
248 }
249 #else
250 #define do_leds()
251 #endif
252
253 void do_gettimeofday(struct timeval *tv)
254 {
255         unsigned long flags;
256         unsigned long seq;
257         unsigned long usec, sec, lost;
258
259         do {
260                 seq = read_seqbegin_irqsave(&xtime_lock, flags);
261                 usec = gettimeoffset();
262
263                 lost = jiffies - wall_jiffies;
264                 if (lost)
265                         usec += lost * USECS_PER_JIFFY;
266
267                 sec = xtime.tv_sec;
268                 usec += xtime.tv_nsec / 1000;
269         } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
270
271         /* usec may have gone up a lot: be safe */
272         while (usec >= 1000000) {
273                 usec -= 1000000;
274                 sec++;
275         }
276
277         tv->tv_sec = sec;
278         tv->tv_usec = usec;
279 }
280
281 EXPORT_SYMBOL(do_gettimeofday);
282
283 int do_settimeofday(struct timespec *tv)
284 {
285         time_t wtm_sec, sec = tv->tv_sec;
286         long wtm_nsec, nsec = tv->tv_nsec;
287
288         if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
289                 return -EINVAL;
290
291         write_seqlock_irq(&xtime_lock);
292         /*
293          * This is revolting. We need to set "xtime" correctly. However, the
294          * value in this location is the value at the most recent update of
295          * wall time.  Discover what correction gettimeofday() would have
296          * done, and then undo it!
297          */
298         nsec -= gettimeoffset() * NSEC_PER_USEC;
299         nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
300
301         wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
302         wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
303
304         set_normalized_timespec(&xtime, sec, nsec);
305         set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
306
307         time_adjust = 0;                /* stop active adjtime() */
308         time_status |= STA_UNSYNC;
309         time_maxerror = NTP_PHASE_LIMIT;
310         time_esterror = NTP_PHASE_LIMIT;
311         write_sequnlock_irq(&xtime_lock);
312         clock_was_set();
313         return 0;
314 }
315
316 EXPORT_SYMBOL(do_settimeofday);
317
318 void timer_tick(struct pt_regs *regs)
319 {
320         do_profile(regs);
321         do_leds();
322         do_set_rtc();
323         do_timer(regs);
324 }
325
326 void (*init_arch_time)(void);
327
328 void __init time_init(void)
329 {
330         init_arch_time();
331 }
332