]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/arch/alpha/kernel/time.c | |
3 | * | |
4 | * Copyright (C) 1991, 1992, 1995, 1999, 2000 Linus Torvalds | |
5 | * | |
85d0b3a5 | 6 | * This file contains the clocksource time handling. |
1da177e4 LT |
7 | * 1997-09-10 Updated NTP code according to technical memorandum Jan '96 |
8 | * "A Kernel Model for Precision Timekeeping" by Dave Mills | |
9 | * 1997-01-09 Adrian Sun | |
10 | * use interval timer if CONFIG_RTC=y | |
11 | * 1997-10-29 John Bowman (bowman@math.ualberta.ca) | |
12 | * fixed tick loss calculation in timer_interrupt | |
13 | * (round system clock to nearest tick instead of truncating) | |
14 | * fixed algorithm in time_init for getting time from CMOS clock | |
15 | * 1999-04-16 Thorsten Kranzkowski (dl8bcu@gmx.net) | |
16 | * fixed algorithm in do_gettimeofday() for calculating the precise time | |
17 | * from processor cycle counter (now taking lost_ticks into account) | |
1da177e4 LT |
18 | * 2003-06-03 R. Scott Bailey <scott.bailey@eds.com> |
19 | * Tighten sanity in time_init from 1% (10,000 PPM) to 250 PPM | |
20 | */ | |
1da177e4 LT |
21 | #include <linux/errno.h> |
22 | #include <linux/module.h> | |
23 | #include <linux/sched.h> | |
24 | #include <linux/kernel.h> | |
25 | #include <linux/param.h> | |
26 | #include <linux/string.h> | |
27 | #include <linux/mm.h> | |
28 | #include <linux/delay.h> | |
29 | #include <linux/ioport.h> | |
30 | #include <linux/irq.h> | |
31 | #include <linux/interrupt.h> | |
32 | #include <linux/init.h> | |
33 | #include <linux/bcd.h> | |
34 | #include <linux/profile.h> | |
e360adbe | 35 | #include <linux/irq_work.h> |
1da177e4 | 36 | |
7c0f6ba6 | 37 | #include <linux/uaccess.h> |
1da177e4 LT |
38 | #include <asm/io.h> |
39 | #include <asm/hwrpb.h> | |
1da177e4 LT |
40 | |
41 | #include <linux/mc146818rtc.h> | |
42 | #include <linux/time.h> | |
43 | #include <linux/timex.h> | |
9ce34c8f | 44 | #include <linux/clocksource.h> |
a1659d6d | 45 | #include <linux/clockchips.h> |
1da177e4 LT |
46 | |
47 | #include "proto.h" | |
48 | #include "irq_impl.h" | |
49 | ||
1da177e4 | 50 | DEFINE_SPINLOCK(rtc_lock); |
cff52daf | 51 | EXPORT_SYMBOL(rtc_lock); |
1da177e4 | 52 | |
1da177e4 LT |
53 | unsigned long est_cycle_freq; |
54 | ||
e360adbe | 55 | #ifdef CONFIG_IRQ_WORK |
979f8671 | 56 | |
e360adbe | 57 | DEFINE_PER_CPU(u8, irq_work_pending); |
979f8671 | 58 | |
2999a4b3 CL |
59 | #define set_irq_work_pending_flag() __this_cpu_write(irq_work_pending, 1) |
60 | #define test_irq_work_pending() __this_cpu_read(irq_work_pending) | |
61 | #define clear_irq_work_pending() __this_cpu_write(irq_work_pending, 0) | |
979f8671 | 62 | |
0f933625 | 63 | void arch_irq_work_raise(void) |
979f8671 | 64 | { |
e360adbe | 65 | set_irq_work_pending_flag(); |
979f8671 MC |
66 | } |
67 | ||
e360adbe | 68 | #else /* CONFIG_IRQ_WORK */ |
979f8671 | 69 | |
e360adbe PZ |
70 | #define test_irq_work_pending() 0 |
71 | #define clear_irq_work_pending() | |
979f8671 | 72 | |
e360adbe | 73 | #endif /* CONFIG_IRQ_WORK */ |
979f8671 | 74 | |
1da177e4 LT |
75 | |
76 | static inline __u32 rpcc(void) | |
77 | { | |
91531b05 | 78 | return __builtin_alpha_rpcc(); |
1da177e4 LT |
79 | } |
80 | ||
a1659d6d RH |
81 | |
82 | \f | |
1da177e4 | 83 | /* |
a1659d6d | 84 | * The RTC as a clock_event_device primitive. |
1da177e4 | 85 | */ |
1da177e4 | 86 | |
a1659d6d | 87 | static DEFINE_PER_CPU(struct clock_event_device, cpu_ce); |
1da177e4 | 88 | |
a1659d6d | 89 | irqreturn_t |
4914d7b4 | 90 | rtc_timer_interrupt(int irq, void *dev) |
a1659d6d RH |
91 | { |
92 | int cpu = smp_processor_id(); | |
93 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | |
1da177e4 | 94 | |
a1659d6d | 95 | /* Don't run the hook for UNUSED or SHUTDOWN. */ |
6ec81932 | 96 | if (likely(clockevent_state_periodic(ce))) |
a1659d6d | 97 | ce->event_handler(ce); |
aa02cd2d | 98 | |
e360adbe PZ |
99 | if (test_irq_work_pending()) { |
100 | clear_irq_work_pending(); | |
101 | irq_work_run(); | |
979f8671 MC |
102 | } |
103 | ||
1da177e4 LT |
104 | return IRQ_HANDLED; |
105 | } | |
106 | ||
a1659d6d RH |
107 | static int |
108 | rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce) | |
109 | { | |
110 | /* This hook is for oneshot mode, which we don't support. */ | |
111 | return -EINVAL; | |
112 | } | |
113 | ||
4914d7b4 RH |
114 | static void __init |
115 | init_rtc_clockevent(void) | |
a1659d6d RH |
116 | { |
117 | int cpu = smp_processor_id(); | |
118 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | |
119 | ||
120 | *ce = (struct clock_event_device){ | |
121 | .name = "rtc", | |
122 | .features = CLOCK_EVT_FEAT_PERIODIC, | |
123 | .rating = 100, | |
124 | .cpumask = cpumask_of(cpu), | |
a1659d6d RH |
125 | .set_next_event = rtc_ce_set_next_event, |
126 | }; | |
127 | ||
128 | clockevents_config_and_register(ce, CONFIG_HZ, 0, 0); | |
129 | } | |
130 | ||
4914d7b4 RH |
131 | \f |
132 | /* | |
133 | * The QEMU clock as a clocksource primitive. | |
134 | */ | |
135 | ||
a5a1d1c2 | 136 | static u64 |
4914d7b4 RH |
137 | qemu_cs_read(struct clocksource *cs) |
138 | { | |
139 | return qemu_get_vmtime(); | |
140 | } | |
141 | ||
142 | static struct clocksource qemu_cs = { | |
143 | .name = "qemu", | |
144 | .rating = 400, | |
145 | .read = qemu_cs_read, | |
146 | .mask = CLOCKSOURCE_MASK(64), | |
147 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | |
148 | .max_idle_ns = LONG_MAX | |
149 | }; | |
150 | ||
151 | ||
152 | /* | |
153 | * The QEMU alarm as a clock_event_device primitive. | |
154 | */ | |
155 | ||
6ec81932 | 156 | static int qemu_ce_shutdown(struct clock_event_device *ce) |
4914d7b4 RH |
157 | { |
158 | /* The mode member of CE is updated for us in generic code. | |
159 | Just make sure that the event is disabled. */ | |
160 | qemu_set_alarm_abs(0); | |
6ec81932 | 161 | return 0; |
4914d7b4 RH |
162 | } |
163 | ||
164 | static int | |
165 | qemu_ce_set_next_event(unsigned long evt, struct clock_event_device *ce) | |
166 | { | |
167 | qemu_set_alarm_rel(evt); | |
168 | return 0; | |
169 | } | |
170 | ||
171 | static irqreturn_t | |
172 | qemu_timer_interrupt(int irq, void *dev) | |
173 | { | |
174 | int cpu = smp_processor_id(); | |
175 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | |
176 | ||
177 | ce->event_handler(ce); | |
178 | return IRQ_HANDLED; | |
179 | } | |
180 | ||
181 | static void __init | |
182 | init_qemu_clockevent(void) | |
183 | { | |
184 | int cpu = smp_processor_id(); | |
185 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | |
186 | ||
187 | *ce = (struct clock_event_device){ | |
188 | .name = "qemu", | |
189 | .features = CLOCK_EVT_FEAT_ONESHOT, | |
190 | .rating = 400, | |
191 | .cpumask = cpumask_of(cpu), | |
6ec81932 VK |
192 | .set_state_shutdown = qemu_ce_shutdown, |
193 | .set_state_oneshot = qemu_ce_shutdown, | |
194 | .tick_resume = qemu_ce_shutdown, | |
4914d7b4 RH |
195 | .set_next_event = qemu_ce_set_next_event, |
196 | }; | |
197 | ||
198 | clockevents_config_and_register(ce, NSEC_PER_SEC, 1000, LONG_MAX); | |
199 | } | |
200 | ||
201 | \f | |
ebaf4fc1 | 202 | void __init |
1da177e4 LT |
203 | common_init_rtc(void) |
204 | { | |
fddd87d6 | 205 | unsigned char x, sel = 0; |
1da177e4 LT |
206 | |
207 | /* Reset periodic interrupt frequency. */ | |
fddd87d6 RH |
208 | #if CONFIG_HZ == 1024 || CONFIG_HZ == 1200 |
209 | x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f; | |
210 | /* Test includes known working values on various platforms | |
211 | where 0x26 is wrong; we refuse to change those. */ | |
212 | if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) { | |
213 | sel = RTC_REF_CLCK_32KHZ + 6; | |
1da177e4 | 214 | } |
fddd87d6 RH |
215 | #elif CONFIG_HZ == 256 || CONFIG_HZ == 128 || CONFIG_HZ == 64 || CONFIG_HZ == 32 |
216 | sel = RTC_REF_CLCK_32KHZ + __builtin_ffs(32768 / CONFIG_HZ); | |
217 | #else | |
218 | # error "Unknown HZ from arch/alpha/Kconfig" | |
219 | #endif | |
220 | if (sel) { | |
221 | printk(KERN_INFO "Setting RTC_FREQ to %d Hz (%x)\n", | |
222 | CONFIG_HZ, sel); | |
223 | CMOS_WRITE(sel, RTC_FREQ_SELECT); | |
224 | } | |
1da177e4 LT |
225 | |
226 | /* Turn on periodic interrupts. */ | |
227 | x = CMOS_READ(RTC_CONTROL); | |
228 | if (!(x & RTC_PIE)) { | |
229 | printk("Turning on RTC interrupts.\n"); | |
230 | x |= RTC_PIE; | |
231 | x &= ~(RTC_AIE | RTC_UIE); | |
232 | CMOS_WRITE(x, RTC_CONTROL); | |
233 | } | |
234 | (void) CMOS_READ(RTC_INTR_FLAGS); | |
235 | ||
236 | outb(0x36, 0x43); /* pit counter 0: system timer */ | |
237 | outb(0x00, 0x40); | |
238 | outb(0x00, 0x40); | |
239 | ||
240 | outb(0xb6, 0x43); /* pit counter 2: speaker */ | |
241 | outb(0x31, 0x42); | |
242 | outb(0x13, 0x42); | |
243 | ||
244 | init_rtc_irq(); | |
245 | } | |
246 | ||
db2d3260 RH |
247 | \f |
248 | #ifndef CONFIG_ALPHA_WTINT | |
249 | /* | |
250 | * The RPCC as a clocksource primitive. | |
251 | * | |
252 | * While we have free-running timecounters running on all CPUs, and we make | |
253 | * a half-hearted attempt in init_rtc_rpcc_info to sync the timecounter | |
254 | * with the wall clock, that initialization isn't kept up-to-date across | |
255 | * different time counters in SMP mode. Therefore we can only use this | |
256 | * method when there's only one CPU enabled. | |
257 | * | |
258 | * When using the WTINT PALcall, the RPCC may shift to a lower frequency, | |
259 | * or stop altogether, while waiting for the interrupt. Therefore we cannot | |
260 | * use this method when WTINT is in use. | |
261 | */ | |
262 | ||
a5a1d1c2 | 263 | static u64 read_rpcc(struct clocksource *cs) |
db2d3260 RH |
264 | { |
265 | return rpcc(); | |
266 | } | |
267 | ||
268 | static struct clocksource clocksource_rpcc = { | |
269 | .name = "rpcc", | |
270 | .rating = 300, | |
271 | .read = read_rpcc, | |
272 | .mask = CLOCKSOURCE_MASK(32), | |
273 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | |
274 | }; | |
275 | #endif /* ALPHA_WTINT */ | |
276 | ||
277 | \f | |
1da177e4 LT |
278 | /* Validate a computed cycle counter result against the known bounds for |
279 | the given processor core. There's too much brokenness in the way of | |
280 | timing hardware for any one method to work everywhere. :-( | |
281 | ||
282 | Return 0 if the result cannot be trusted, otherwise return the argument. */ | |
283 | ||
284 | static unsigned long __init | |
285 | validate_cc_value(unsigned long cc) | |
286 | { | |
287 | static struct bounds { | |
288 | unsigned int min, max; | |
289 | } cpu_hz[] __initdata = { | |
290 | [EV3_CPU] = { 50000000, 200000000 }, /* guess */ | |
291 | [EV4_CPU] = { 100000000, 300000000 }, | |
292 | [LCA4_CPU] = { 100000000, 300000000 }, /* guess */ | |
293 | [EV45_CPU] = { 200000000, 300000000 }, | |
294 | [EV5_CPU] = { 250000000, 433000000 }, | |
295 | [EV56_CPU] = { 333000000, 667000000 }, | |
296 | [PCA56_CPU] = { 400000000, 600000000 }, /* guess */ | |
297 | [PCA57_CPU] = { 500000000, 600000000 }, /* guess */ | |
298 | [EV6_CPU] = { 466000000, 600000000 }, | |
299 | [EV67_CPU] = { 600000000, 750000000 }, | |
300 | [EV68AL_CPU] = { 750000000, 940000000 }, | |
301 | [EV68CB_CPU] = { 1000000000, 1333333333 }, | |
302 | /* None of the following are shipping as of 2001-11-01. */ | |
303 | [EV68CX_CPU] = { 1000000000, 1700000000 }, /* guess */ | |
304 | [EV69_CPU] = { 1000000000, 1700000000 }, /* guess */ | |
305 | [EV7_CPU] = { 800000000, 1400000000 }, /* guess */ | |
306 | [EV79_CPU] = { 1000000000, 2000000000 }, /* guess */ | |
307 | }; | |
308 | ||
309 | /* Allow for some drift in the crystal. 10MHz is more than enough. */ | |
310 | const unsigned int deviation = 10000000; | |
311 | ||
312 | struct percpu_struct *cpu; | |
313 | unsigned int index; | |
314 | ||
315 | cpu = (struct percpu_struct *)((char*)hwrpb + hwrpb->processor_offset); | |
316 | index = cpu->type & 0xffffffff; | |
317 | ||
318 | /* If index out of bounds, no way to validate. */ | |
25c8716c | 319 | if (index >= ARRAY_SIZE(cpu_hz)) |
1da177e4 LT |
320 | return cc; |
321 | ||
322 | /* If index contains no data, no way to validate. */ | |
323 | if (cpu_hz[index].max == 0) | |
324 | return cc; | |
325 | ||
326 | if (cc < cpu_hz[index].min - deviation | |
327 | || cc > cpu_hz[index].max + deviation) | |
328 | return 0; | |
329 | ||
330 | return cc; | |
331 | } | |
332 | ||
333 | ||
334 | /* | |
335 | * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from | |
336 | * arch/i386/time.c. | |
337 | */ | |
338 | ||
339 | #define CALIBRATE_LATCH 0xffff | |
340 | #define TIMEOUT_COUNT 0x100000 | |
341 | ||
342 | static unsigned long __init | |
343 | calibrate_cc_with_pit(void) | |
344 | { | |
345 | int cc, count = 0; | |
346 | ||
347 | /* Set the Gate high, disable speaker */ | |
348 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | |
349 | ||
350 | /* | |
351 | * Now let's take care of CTC channel 2 | |
352 | * | |
353 | * Set the Gate high, program CTC channel 2 for mode 0, | |
354 | * (interrupt on terminal count mode), binary count, | |
355 | * load 5 * LATCH count, (LSB and MSB) to begin countdown. | |
356 | */ | |
357 | outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ | |
358 | outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */ | |
359 | outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */ | |
360 | ||
361 | cc = rpcc(); | |
362 | do { | |
363 | count++; | |
364 | } while ((inb(0x61) & 0x20) == 0 && count < TIMEOUT_COUNT); | |
365 | cc = rpcc() - cc; | |
366 | ||
367 | /* Error: ECTCNEVERSET or ECPUTOOFAST. */ | |
368 | if (count <= 1 || count == TIMEOUT_COUNT) | |
369 | return 0; | |
370 | ||
371 | return ((long)cc * PIT_TICK_RATE) / (CALIBRATE_LATCH + 1); | |
372 | } | |
373 | ||
374 | /* The Linux interpretation of the CMOS clock register contents: | |
375 | When the Update-In-Progress (UIP) flag goes from 1 to 0, the | |
376 | RTC registers show the second which has precisely just started. | |
377 | Let's hope other operating systems interpret the RTC the same way. */ | |
378 | ||
379 | static unsigned long __init | |
380 | rpcc_after_update_in_progress(void) | |
381 | { | |
382 | do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); | |
383 | do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); | |
384 | ||
385 | return rpcc(); | |
386 | } | |
387 | ||
388 | void __init | |
389 | time_init(void) | |
390 | { | |
1e871be1 | 391 | unsigned int cc1, cc2; |
1da177e4 LT |
392 | unsigned long cycle_freq, tolerance; |
393 | long diff; | |
394 | ||
4914d7b4 RH |
395 | if (alpha_using_qemu) { |
396 | clocksource_register_hz(&qemu_cs, NSEC_PER_SEC); | |
397 | init_qemu_clockevent(); | |
398 | ||
399 | timer_irqaction.handler = qemu_timer_interrupt; | |
400 | init_rtc_irq(); | |
401 | return; | |
402 | } | |
403 | ||
1da177e4 LT |
404 | /* Calibrate CPU clock -- attempt #1. */ |
405 | if (!est_cycle_freq) | |
406 | est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); | |
407 | ||
4c2e6f6a | 408 | cc1 = rpcc(); |
1da177e4 LT |
409 | |
410 | /* Calibrate CPU clock -- attempt #2. */ | |
411 | if (!est_cycle_freq) { | |
4c2e6f6a | 412 | cc1 = rpcc_after_update_in_progress(); |
1da177e4 LT |
413 | cc2 = rpcc_after_update_in_progress(); |
414 | est_cycle_freq = validate_cc_value(cc2 - cc1); | |
415 | cc1 = cc2; | |
416 | } | |
417 | ||
418 | cycle_freq = hwrpb->cycle_freq; | |
419 | if (est_cycle_freq) { | |
420 | /* If the given value is within 250 PPM of what we calculated, | |
421 | accept it. Otherwise, use what we found. */ | |
422 | tolerance = cycle_freq / 4000; | |
423 | diff = cycle_freq - est_cycle_freq; | |
424 | if (diff < 0) | |
425 | diff = -diff; | |
426 | if ((unsigned long)diff > tolerance) { | |
427 | cycle_freq = est_cycle_freq; | |
428 | printk("HWRPB cycle frequency bogus. " | |
429 | "Estimated %lu Hz\n", cycle_freq); | |
430 | } else { | |
431 | est_cycle_freq = 0; | |
432 | } | |
433 | } else if (! validate_cc_value (cycle_freq)) { | |
434 | printk("HWRPB cycle frequency bogus, " | |
435 | "and unable to estimate a proper value!\n"); | |
436 | } | |
437 | ||
db2d3260 RH |
438 | /* See above for restrictions on using clocksource_rpcc. */ |
439 | #ifndef CONFIG_ALPHA_WTINT | |
440 | if (hwrpb->nr_processors == 1) | |
441 | clocksource_register_hz(&clocksource_rpcc, cycle_freq); | |
442 | #endif | |
443 | ||
1da177e4 LT |
444 | /* Startup the timer source. */ |
445 | alpha_mv.init_rtc(); | |
4914d7b4 RH |
446 | init_rtc_clockevent(); |
447 | } | |
a1659d6d | 448 | |
4914d7b4 RH |
449 | /* Initialize the clock_event_device for secondary cpus. */ |
450 | #ifdef CONFIG_SMP | |
451 | void __init | |
452 | init_clockevent(void) | |
453 | { | |
454 | if (alpha_using_qemu) | |
455 | init_qemu_clockevent(); | |
456 | else | |
457 | init_rtc_clockevent(); | |
1da177e4 | 458 | } |
4914d7b4 | 459 | #endif |