ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / kernel / sn2 / timer.c
1 /*
2  * linux/arch/ia64/sn/kernel/sn2/timer.c
3  *
4  * Copyright (C) 2003 Silicon Graphics, Inc.
5  * Copyright (C) 2003 Hewlett-Packard Co
6  *      David Mosberger <davidm@hpl.hp.com>: updated for new timer-interpolation infrastructure
7  */
8
9 #include <linux/init.h>
10 #include <linux/kernel.h>
11 #include <linux/sched.h>
12 #include <linux/time.h>
13 #include <linux/interrupt.h>
14
15 #include <asm/hw_irq.h>
16 #include <asm/system.h>
17
18 #include <asm/sn/leds.h>
19 #include <asm/sn/clksupport.h>
20
21
22 extern unsigned long sn_rtc_cycles_per_second;
23 static volatile unsigned long last_wall_rtc;
24
25 static unsigned long rtc_offset;        /* updated only when xtime write-lock is held! */
26 static long rtc_nsecs_per_cycle;
27 static long rtc_per_timer_tick;
28
29 static unsigned long
30 getoffset(void)
31 {
32         return rtc_offset + (GET_RTC_COUNTER() - last_wall_rtc)*rtc_nsecs_per_cycle;
33 }
34
35
36 static void
37 update(long delta_nsec)
38 {
39         unsigned long rtc_counter = GET_RTC_COUNTER();
40         unsigned long offset = rtc_offset + (rtc_counter - last_wall_rtc)*rtc_nsecs_per_cycle;
41
42         /* Be careful about signed/unsigned comparisons here: */
43         if (delta_nsec < 0 || (unsigned long) delta_nsec < offset)
44                 rtc_offset = offset - delta_nsec;
45         else
46                 rtc_offset = 0;
47         last_wall_rtc = rtc_counter;
48 }
49
50
51 static void
52 reset(void)
53 {
54         rtc_offset = 0;
55         last_wall_rtc = GET_RTC_COUNTER();
56 }
57
58
59 static struct time_interpolator sn2_interpolator = {
60         .get_offset =   getoffset,
61         .update =       update,
62         .reset =        reset
63 };
64
65 void __init
66 sn_timer_init(void)
67 {
68         sn2_interpolator.frequency = sn_rtc_cycles_per_second;
69         sn2_interpolator.drift = -1;    /* unknown */
70         register_time_interpolator(&sn2_interpolator);
71
72         rtc_per_timer_tick = sn_rtc_cycles_per_second / HZ;
73         rtc_nsecs_per_cycle = 1000000000 / sn_rtc_cycles_per_second;
74
75         last_wall_rtc = GET_RTC_COUNTER();
76 }