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 LT |
36 | |
37 | #include <asm/uaccess.h> | |
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 RH |
95 | /* Don't run the hook for UNUSED or SHUTDOWN. */ |
96 | if (likely(ce->mode == CLOCK_EVT_MODE_PERIODIC)) | |
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 void |
108 | rtc_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) | |
109 | { | |
110 | /* The mode member of CE is updated in generic code. | |
111 | Since we only support periodic events, nothing to do. */ | |
112 | } | |
113 | ||
114 | static int | |
115 | rtc_ce_set_next_event(unsigned long evt, struct clock_event_device *ce) | |
116 | { | |
117 | /* This hook is for oneshot mode, which we don't support. */ | |
118 | return -EINVAL; | |
119 | } | |
120 | ||
4914d7b4 RH |
121 | static void __init |
122 | init_rtc_clockevent(void) | |
a1659d6d RH |
123 | { |
124 | int cpu = smp_processor_id(); | |
125 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | |
126 | ||
127 | *ce = (struct clock_event_device){ | |
128 | .name = "rtc", | |
129 | .features = CLOCK_EVT_FEAT_PERIODIC, | |
130 | .rating = 100, | |
131 | .cpumask = cpumask_of(cpu), | |
132 | .set_mode = rtc_ce_set_mode, | |
133 | .set_next_event = rtc_ce_set_next_event, | |
134 | }; | |
135 | ||
136 | clockevents_config_and_register(ce, CONFIG_HZ, 0, 0); | |
137 | } | |
138 | ||
4914d7b4 RH |
139 | \f |
140 | /* | |
141 | * The QEMU clock as a clocksource primitive. | |
142 | */ | |
143 | ||
144 | static cycle_t | |
145 | qemu_cs_read(struct clocksource *cs) | |
146 | { | |
147 | return qemu_get_vmtime(); | |
148 | } | |
149 | ||
150 | static struct clocksource qemu_cs = { | |
151 | .name = "qemu", | |
152 | .rating = 400, | |
153 | .read = qemu_cs_read, | |
154 | .mask = CLOCKSOURCE_MASK(64), | |
155 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | |
156 | .max_idle_ns = LONG_MAX | |
157 | }; | |
158 | ||
159 | ||
160 | /* | |
161 | * The QEMU alarm as a clock_event_device primitive. | |
162 | */ | |
163 | ||
164 | static void | |
165 | qemu_ce_set_mode(enum clock_event_mode mode, struct clock_event_device *ce) | |
166 | { | |
167 | /* The mode member of CE is updated for us in generic code. | |
168 | Just make sure that the event is disabled. */ | |
169 | qemu_set_alarm_abs(0); | |
170 | } | |
171 | ||
172 | static int | |
173 | qemu_ce_set_next_event(unsigned long evt, struct clock_event_device *ce) | |
174 | { | |
175 | qemu_set_alarm_rel(evt); | |
176 | return 0; | |
177 | } | |
178 | ||
179 | static irqreturn_t | |
180 | qemu_timer_interrupt(int irq, void *dev) | |
181 | { | |
182 | int cpu = smp_processor_id(); | |
183 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | |
184 | ||
185 | ce->event_handler(ce); | |
186 | return IRQ_HANDLED; | |
187 | } | |
188 | ||
189 | static void __init | |
190 | init_qemu_clockevent(void) | |
191 | { | |
192 | int cpu = smp_processor_id(); | |
193 | struct clock_event_device *ce = &per_cpu(cpu_ce, cpu); | |
194 | ||
195 | *ce = (struct clock_event_device){ | |
196 | .name = "qemu", | |
197 | .features = CLOCK_EVT_FEAT_ONESHOT, | |
198 | .rating = 400, | |
199 | .cpumask = cpumask_of(cpu), | |
200 | .set_mode = qemu_ce_set_mode, | |
201 | .set_next_event = qemu_ce_set_next_event, | |
202 | }; | |
203 | ||
204 | clockevents_config_and_register(ce, NSEC_PER_SEC, 1000, LONG_MAX); | |
205 | } | |
206 | ||
207 | \f | |
ebaf4fc1 | 208 | void __init |
1da177e4 LT |
209 | common_init_rtc(void) |
210 | { | |
fddd87d6 | 211 | unsigned char x, sel = 0; |
1da177e4 LT |
212 | |
213 | /* Reset periodic interrupt frequency. */ | |
fddd87d6 RH |
214 | #if CONFIG_HZ == 1024 || CONFIG_HZ == 1200 |
215 | x = CMOS_READ(RTC_FREQ_SELECT) & 0x3f; | |
216 | /* Test includes known working values on various platforms | |
217 | where 0x26 is wrong; we refuse to change those. */ | |
218 | if (x != 0x26 && x != 0x25 && x != 0x19 && x != 0x06) { | |
219 | sel = RTC_REF_CLCK_32KHZ + 6; | |
1da177e4 | 220 | } |
fddd87d6 RH |
221 | #elif CONFIG_HZ == 256 || CONFIG_HZ == 128 || CONFIG_HZ == 64 || CONFIG_HZ == 32 |
222 | sel = RTC_REF_CLCK_32KHZ + __builtin_ffs(32768 / CONFIG_HZ); | |
223 | #else | |
224 | # error "Unknown HZ from arch/alpha/Kconfig" | |
225 | #endif | |
226 | if (sel) { | |
227 | printk(KERN_INFO "Setting RTC_FREQ to %d Hz (%x)\n", | |
228 | CONFIG_HZ, sel); | |
229 | CMOS_WRITE(sel, RTC_FREQ_SELECT); | |
230 | } | |
1da177e4 LT |
231 | |
232 | /* Turn on periodic interrupts. */ | |
233 | x = CMOS_READ(RTC_CONTROL); | |
234 | if (!(x & RTC_PIE)) { | |
235 | printk("Turning on RTC interrupts.\n"); | |
236 | x |= RTC_PIE; | |
237 | x &= ~(RTC_AIE | RTC_UIE); | |
238 | CMOS_WRITE(x, RTC_CONTROL); | |
239 | } | |
240 | (void) CMOS_READ(RTC_INTR_FLAGS); | |
241 | ||
242 | outb(0x36, 0x43); /* pit counter 0: system timer */ | |
243 | outb(0x00, 0x40); | |
244 | outb(0x00, 0x40); | |
245 | ||
246 | outb(0xb6, 0x43); /* pit counter 2: speaker */ | |
247 | outb(0x31, 0x42); | |
248 | outb(0x13, 0x42); | |
249 | ||
250 | init_rtc_irq(); | |
251 | } | |
252 | ||
db2d3260 RH |
253 | \f |
254 | #ifndef CONFIG_ALPHA_WTINT | |
255 | /* | |
256 | * The RPCC as a clocksource primitive. | |
257 | * | |
258 | * While we have free-running timecounters running on all CPUs, and we make | |
259 | * a half-hearted attempt in init_rtc_rpcc_info to sync the timecounter | |
260 | * with the wall clock, that initialization isn't kept up-to-date across | |
261 | * different time counters in SMP mode. Therefore we can only use this | |
262 | * method when there's only one CPU enabled. | |
263 | * | |
264 | * When using the WTINT PALcall, the RPCC may shift to a lower frequency, | |
265 | * or stop altogether, while waiting for the interrupt. Therefore we cannot | |
266 | * use this method when WTINT is in use. | |
267 | */ | |
268 | ||
269 | static cycle_t read_rpcc(struct clocksource *cs) | |
270 | { | |
271 | return rpcc(); | |
272 | } | |
273 | ||
274 | static struct clocksource clocksource_rpcc = { | |
275 | .name = "rpcc", | |
276 | .rating = 300, | |
277 | .read = read_rpcc, | |
278 | .mask = CLOCKSOURCE_MASK(32), | |
279 | .flags = CLOCK_SOURCE_IS_CONTINUOUS | |
280 | }; | |
281 | #endif /* ALPHA_WTINT */ | |
282 | ||
283 | \f | |
1da177e4 LT |
284 | /* Validate a computed cycle counter result against the known bounds for |
285 | the given processor core. There's too much brokenness in the way of | |
286 | timing hardware for any one method to work everywhere. :-( | |
287 | ||
288 | Return 0 if the result cannot be trusted, otherwise return the argument. */ | |
289 | ||
290 | static unsigned long __init | |
291 | validate_cc_value(unsigned long cc) | |
292 | { | |
293 | static struct bounds { | |
294 | unsigned int min, max; | |
295 | } cpu_hz[] __initdata = { | |
296 | [EV3_CPU] = { 50000000, 200000000 }, /* guess */ | |
297 | [EV4_CPU] = { 100000000, 300000000 }, | |
298 | [LCA4_CPU] = { 100000000, 300000000 }, /* guess */ | |
299 | [EV45_CPU] = { 200000000, 300000000 }, | |
300 | [EV5_CPU] = { 250000000, 433000000 }, | |
301 | [EV56_CPU] = { 333000000, 667000000 }, | |
302 | [PCA56_CPU] = { 400000000, 600000000 }, /* guess */ | |
303 | [PCA57_CPU] = { 500000000, 600000000 }, /* guess */ | |
304 | [EV6_CPU] = { 466000000, 600000000 }, | |
305 | [EV67_CPU] = { 600000000, 750000000 }, | |
306 | [EV68AL_CPU] = { 750000000, 940000000 }, | |
307 | [EV68CB_CPU] = { 1000000000, 1333333333 }, | |
308 | /* None of the following are shipping as of 2001-11-01. */ | |
309 | [EV68CX_CPU] = { 1000000000, 1700000000 }, /* guess */ | |
310 | [EV69_CPU] = { 1000000000, 1700000000 }, /* guess */ | |
311 | [EV7_CPU] = { 800000000, 1400000000 }, /* guess */ | |
312 | [EV79_CPU] = { 1000000000, 2000000000 }, /* guess */ | |
313 | }; | |
314 | ||
315 | /* Allow for some drift in the crystal. 10MHz is more than enough. */ | |
316 | const unsigned int deviation = 10000000; | |
317 | ||
318 | struct percpu_struct *cpu; | |
319 | unsigned int index; | |
320 | ||
321 | cpu = (struct percpu_struct *)((char*)hwrpb + hwrpb->processor_offset); | |
322 | index = cpu->type & 0xffffffff; | |
323 | ||
324 | /* If index out of bounds, no way to validate. */ | |
25c8716c | 325 | if (index >= ARRAY_SIZE(cpu_hz)) |
1da177e4 LT |
326 | return cc; |
327 | ||
328 | /* If index contains no data, no way to validate. */ | |
329 | if (cpu_hz[index].max == 0) | |
330 | return cc; | |
331 | ||
332 | if (cc < cpu_hz[index].min - deviation | |
333 | || cc > cpu_hz[index].max + deviation) | |
334 | return 0; | |
335 | ||
336 | return cc; | |
337 | } | |
338 | ||
339 | ||
340 | /* | |
341 | * Calibrate CPU clock using legacy 8254 timer/counter. Stolen from | |
342 | * arch/i386/time.c. | |
343 | */ | |
344 | ||
345 | #define CALIBRATE_LATCH 0xffff | |
346 | #define TIMEOUT_COUNT 0x100000 | |
347 | ||
348 | static unsigned long __init | |
349 | calibrate_cc_with_pit(void) | |
350 | { | |
351 | int cc, count = 0; | |
352 | ||
353 | /* Set the Gate high, disable speaker */ | |
354 | outb((inb(0x61) & ~0x02) | 0x01, 0x61); | |
355 | ||
356 | /* | |
357 | * Now let's take care of CTC channel 2 | |
358 | * | |
359 | * Set the Gate high, program CTC channel 2 for mode 0, | |
360 | * (interrupt on terminal count mode), binary count, | |
361 | * load 5 * LATCH count, (LSB and MSB) to begin countdown. | |
362 | */ | |
363 | outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */ | |
364 | outb(CALIBRATE_LATCH & 0xff, 0x42); /* LSB of count */ | |
365 | outb(CALIBRATE_LATCH >> 8, 0x42); /* MSB of count */ | |
366 | ||
367 | cc = rpcc(); | |
368 | do { | |
369 | count++; | |
370 | } while ((inb(0x61) & 0x20) == 0 && count < TIMEOUT_COUNT); | |
371 | cc = rpcc() - cc; | |
372 | ||
373 | /* Error: ECTCNEVERSET or ECPUTOOFAST. */ | |
374 | if (count <= 1 || count == TIMEOUT_COUNT) | |
375 | return 0; | |
376 | ||
377 | return ((long)cc * PIT_TICK_RATE) / (CALIBRATE_LATCH + 1); | |
378 | } | |
379 | ||
380 | /* The Linux interpretation of the CMOS clock register contents: | |
381 | When the Update-In-Progress (UIP) flag goes from 1 to 0, the | |
382 | RTC registers show the second which has precisely just started. | |
383 | Let's hope other operating systems interpret the RTC the same way. */ | |
384 | ||
385 | static unsigned long __init | |
386 | rpcc_after_update_in_progress(void) | |
387 | { | |
388 | do { } while (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)); | |
389 | do { } while (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP); | |
390 | ||
391 | return rpcc(); | |
392 | } | |
393 | ||
394 | void __init | |
395 | time_init(void) | |
396 | { | |
1e871be1 | 397 | unsigned int cc1, cc2; |
1da177e4 LT |
398 | unsigned long cycle_freq, tolerance; |
399 | long diff; | |
400 | ||
4914d7b4 RH |
401 | if (alpha_using_qemu) { |
402 | clocksource_register_hz(&qemu_cs, NSEC_PER_SEC); | |
403 | init_qemu_clockevent(); | |
404 | ||
405 | timer_irqaction.handler = qemu_timer_interrupt; | |
406 | init_rtc_irq(); | |
407 | return; | |
408 | } | |
409 | ||
1da177e4 LT |
410 | /* Calibrate CPU clock -- attempt #1. */ |
411 | if (!est_cycle_freq) | |
412 | est_cycle_freq = validate_cc_value(calibrate_cc_with_pit()); | |
413 | ||
4c2e6f6a | 414 | cc1 = rpcc(); |
1da177e4 LT |
415 | |
416 | /* Calibrate CPU clock -- attempt #2. */ | |
417 | if (!est_cycle_freq) { | |
4c2e6f6a | 418 | cc1 = rpcc_after_update_in_progress(); |
1da177e4 LT |
419 | cc2 = rpcc_after_update_in_progress(); |
420 | est_cycle_freq = validate_cc_value(cc2 - cc1); | |
421 | cc1 = cc2; | |
422 | } | |
423 | ||
424 | cycle_freq = hwrpb->cycle_freq; | |
425 | if (est_cycle_freq) { | |
426 | /* If the given value is within 250 PPM of what we calculated, | |
427 | accept it. Otherwise, use what we found. */ | |
428 | tolerance = cycle_freq / 4000; | |
429 | diff = cycle_freq - est_cycle_freq; | |
430 | if (diff < 0) | |
431 | diff = -diff; | |
432 | if ((unsigned long)diff > tolerance) { | |
433 | cycle_freq = est_cycle_freq; | |
434 | printk("HWRPB cycle frequency bogus. " | |
435 | "Estimated %lu Hz\n", cycle_freq); | |
436 | } else { | |
437 | est_cycle_freq = 0; | |
438 | } | |
439 | } else if (! validate_cc_value (cycle_freq)) { | |
440 | printk("HWRPB cycle frequency bogus, " | |
441 | "and unable to estimate a proper value!\n"); | |
442 | } | |
443 | ||
db2d3260 RH |
444 | /* See above for restrictions on using clocksource_rpcc. */ |
445 | #ifndef CONFIG_ALPHA_WTINT | |
446 | if (hwrpb->nr_processors == 1) | |
447 | clocksource_register_hz(&clocksource_rpcc, cycle_freq); | |
448 | #endif | |
449 | ||
1da177e4 LT |
450 | /* Startup the timer source. */ |
451 | alpha_mv.init_rtc(); | |
4914d7b4 RH |
452 | init_rtc_clockevent(); |
453 | } | |
a1659d6d | 454 | |
4914d7b4 RH |
455 | /* Initialize the clock_event_device for secondary cpus. */ |
456 | #ifdef CONFIG_SMP | |
457 | void __init | |
458 | init_clockevent(void) | |
459 | { | |
460 | if (alpha_using_qemu) | |
461 | init_qemu_clockevent(); | |
462 | else | |
463 | init_rtc_clockevent(); | |
1da177e4 | 464 | } |
4914d7b4 | 465 | #endif |