]>
Commit | Line | Data |
---|---|---|
daa00b9c | 1 | /* |
1da177e4 LT |
2 | * linux/arch/cris/kernel/time.c |
3 | * | |
4 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds | |
5 | * Copyright (C) 1999, 2000, 2001 Axis Communications AB | |
6 | * | |
7 | * 1994-07-02 Alan Modra | |
8 | * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime | |
9 | * 1995-03-26 Markus Kuhn | |
10 | * fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887 | |
11 | * precision CMOS clock update | |
12 | * 1996-05-03 Ingo Molnar | |
13 | * fixed time warps in do_[slow|fast]_gettimeoffset() | |
14 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 | |
15 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | |
16 | * | |
17 | * Linux/CRIS specific code: | |
18 | * | |
19 | * Authors: Bjorn Wesen | |
daa00b9c | 20 | * Johan Adolfsson |
1da177e4 LT |
21 | * |
22 | */ | |
23 | ||
24 | #include <asm/rtc.h> | |
25 | #include <linux/errno.h> | |
26 | #include <linux/module.h> | |
27 | #include <linux/param.h> | |
28 | #include <linux/jiffies.h> | |
29 | #include <linux/bcd.h> | |
30 | #include <linux/timex.h> | |
31 | #include <linux/init.h> | |
21783c97 | 32 | #include <linux/profile.h> |
4e57b681 | 33 | #include <linux/sched.h> /* just for sched_clock() - funny that */ |
1da177e4 | 34 | |
1da177e4 LT |
35 | int have_rtc; /* used to remember if we have an RTC or not */; |
36 | ||
37 | #define TICK_SIZE tick | |
38 | ||
1da177e4 LT |
39 | extern unsigned long loops_per_jiffy; /* init/main.c */ |
40 | unsigned long loops_per_usec; | |
41 | ||
60dbd663 JN |
42 | |
43 | #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET | |
1da177e4 LT |
44 | extern unsigned long do_slow_gettimeoffset(void); |
45 | static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset; | |
46 | ||
ba875ba6 | 47 | u32 arch_gettimeoffset(void) |
1da177e4 | 48 | { |
60dbd663 | 49 | return do_gettimeoffset() * 1000; |
1da177e4 | 50 | } |
60dbd663 | 51 | #endif |
1da177e4 | 52 | |
1da177e4 LT |
53 | /* |
54 | * BUG: This routine does not handle hour overflow properly; it just | |
55 | * sets the minutes. Usually you'll only notice that after reboot! | |
56 | */ | |
57 | ||
58 | int set_rtc_mmss(unsigned long nowtime) | |
59 | { | |
60 | int retval = 0; | |
61 | int real_seconds, real_minutes, cmos_minutes; | |
62 | ||
63 | printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime); | |
64 | ||
65 | if(!have_rtc) | |
66 | return 0; | |
67 | ||
68 | cmos_minutes = CMOS_READ(RTC_MINUTES); | |
4110a0d6 | 69 | cmos_minutes = bcd2bin(cmos_minutes); |
1da177e4 LT |
70 | |
71 | /* | |
72 | * since we're only adjusting minutes and seconds, | |
73 | * don't interfere with hour overflow. This avoids | |
74 | * messing with unknown time zones but requires your | |
75 | * RTC not to be off by more than 15 minutes | |
76 | */ | |
77 | real_seconds = nowtime % 60; | |
78 | real_minutes = nowtime / 60; | |
79 | if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) | |
80 | real_minutes += 30; /* correct for half hour time zone */ | |
81 | real_minutes %= 60; | |
82 | ||
83 | if (abs(real_minutes - cmos_minutes) < 30) { | |
4110a0d6 AB |
84 | real_seconds = bin2bcd(real_seconds); |
85 | real_minutes = bin2bcd(real_minutes); | |
1da177e4 LT |
86 | CMOS_WRITE(real_seconds,RTC_SECONDS); |
87 | CMOS_WRITE(real_minutes,RTC_MINUTES); | |
88 | } else { | |
3e5c1240 | 89 | printk_once(KERN_NOTICE |
1da177e4 LT |
90 | "set_rtc_mmss: can't update from %d to %d\n", |
91 | cmos_minutes, real_minutes); | |
92 | retval = -1; | |
93 | } | |
94 | ||
95 | return retval; | |
96 | } | |
97 | ||
98 | /* grab the time from the RTC chip */ | |
99 | ||
100 | unsigned long | |
101 | get_cmos_time(void) | |
102 | { | |
103 | unsigned int year, mon, day, hour, min, sec; | |
8eff8a5c JS |
104 | if(!have_rtc) |
105 | return 0; | |
1da177e4 LT |
106 | |
107 | sec = CMOS_READ(RTC_SECONDS); | |
108 | min = CMOS_READ(RTC_MINUTES); | |
109 | hour = CMOS_READ(RTC_HOURS); | |
110 | day = CMOS_READ(RTC_DAY_OF_MONTH); | |
111 | mon = CMOS_READ(RTC_MONTH); | |
112 | year = CMOS_READ(RTC_YEAR); | |
113 | ||
4110a0d6 AB |
114 | sec = bcd2bin(sec); |
115 | min = bcd2bin(min); | |
116 | hour = bcd2bin(hour); | |
117 | day = bcd2bin(day); | |
118 | mon = bcd2bin(mon); | |
119 | year = bcd2bin(year); | |
1da177e4 LT |
120 | |
121 | if ((year += 1900) < 1970) | |
122 | year += 100; | |
123 | ||
124 | return mktime(year, mon, day, hour, min, sec); | |
125 | } | |
126 | ||
1da177e4 | 127 | |
8eff8a5c | 128 | int update_persistent_clock(struct timespec now) |
1da177e4 | 129 | { |
8eff8a5c | 130 | return set_rtc_mmss(now.tv_sec); |
1da177e4 LT |
131 | } |
132 | ||
8eff8a5c JS |
133 | void read_persistent_clock(struct timespec *ts) |
134 | { | |
135 | ts->tv_sec = get_cmos_time(); | |
136 | ts->tv_nsec = 0; | |
137 | } | |
138 | ||
139 | ||
21783c97 MS |
140 | extern void cris_profile_sample(struct pt_regs* regs); |
141 | ||
142 | void | |
143 | cris_do_profile(struct pt_regs* regs) | |
144 | { | |
145 | ||
0188e603 | 146 | #ifdef CONFIG_SYSTEM_PROFILER |
21783c97 MS |
147 | cris_profile_sample(regs); |
148 | #endif | |
149 | ||
0188e603 | 150 | #ifdef CONFIG_PROFILING |
c2610381 | 151 | profile_tick(CPU_PROFILING); |
21783c97 MS |
152 | #endif |
153 | } | |
154 | ||
daa00b9c JN |
155 | unsigned long long sched_clock(void) |
156 | { | |
60dbd663 | 157 | return (unsigned long long)jiffies * (NSEC_PER_SEC / HZ) + |
daa00b9c JN |
158 | get_ns_in_jiffie(); |
159 | } | |
160 | ||
1da177e4 LT |
161 | static int |
162 | __init init_udelay(void) | |
163 | { | |
164 | loops_per_usec = (loops_per_jiffy * HZ) / 1000000; | |
165 | return 0; | |
166 | } | |
167 | ||
168 | __initcall(init_udelay); |