[PATCH] x86_64: Fix drift with HPET timer enabled
[deliverable/linux.git] / arch / x86_64 / kernel / time.c
CommitLineData
1da177e4
LT
1/*
2 * linux/arch/x86-64/kernel/time.c
3 *
4 * "High Precision Event Timer" based timekeeping.
5 *
6 * Copyright (c) 1991,1992,1995 Linus Torvalds
7 * Copyright (c) 1994 Alan Modra
8 * Copyright (c) 1995 Markus Kuhn
9 * Copyright (c) 1996 Ingo Molnar
10 * Copyright (c) 1998 Andrea Arcangeli
11 * Copyright (c) 2002 Vojtech Pavlik
12 * Copyright (c) 2003 Andi Kleen
13 * RTC support code taken from arch/i386/kernel/timers/time_hpet.c
14 */
15
16#include <linux/kernel.h>
17#include <linux/sched.h>
18#include <linux/interrupt.h>
19#include <linux/init.h>
20#include <linux/mc146818rtc.h>
1da177e4
LT
21#include <linux/time.h>
22#include <linux/ioport.h>
23#include <linux/module.h>
24#include <linux/device.h>
25#include <linux/sysdev.h>
26#include <linux/bcd.h>
27#include <linux/kallsyms.h>
312df5f1 28#include <linux/acpi.h>
8d916406 29#ifdef CONFIG_ACPI
312df5f1 30#include <acpi/achware.h> /* for PM timer frequency */
8d916406 31#endif
1da177e4
LT
32#include <asm/8253pit.h>
33#include <asm/pgtable.h>
34#include <asm/vsyscall.h>
35#include <asm/timex.h>
36#include <asm/proto.h>
37#include <asm/hpet.h>
38#include <asm/sections.h>
39#include <linux/cpufreq.h>
40#include <linux/hpet.h>
41#ifdef CONFIG_X86_LOCAL_APIC
42#include <asm/apic.h>
43#endif
44
1da177e4
LT
45#ifdef CONFIG_CPU_FREQ
46static void cpufreq_delayed_get(void);
47#endif
48extern void i8254_timer_resume(void);
49extern int using_apic_timer;
50
e8b91777
AK
51static char *time_init_gtod(void);
52
1da177e4
LT
53DEFINE_SPINLOCK(rtc_lock);
54DEFINE_SPINLOCK(i8253_lock);
55
73dea47f 56int nohpet __initdata = 0;
1da177e4
LT
57static int notsc __initdata = 0;
58
59#undef HPET_HACK_ENABLE_DANGEROUS
60
61unsigned int cpu_khz; /* TSC clocks / usec, not used here */
62static unsigned long hpet_period; /* fsecs / HPET clock */
63unsigned long hpet_tick; /* HPET clocks / interrupt */
33042a9f 64int hpet_use_timer; /* Use counter of hpet for time keeping, otherwise PIT */
1da177e4
LT
65unsigned long vxtime_hz = PIT_TICK_RATE;
66int report_lost_ticks; /* command line option */
67unsigned long long monotonic_base;
68
69struct vxtime_data __vxtime __section_vxtime; /* for vsyscalls */
70
71volatile unsigned long __jiffies __section_jiffies = INITIAL_JIFFIES;
72unsigned long __wall_jiffies __section_wall_jiffies = INITIAL_JIFFIES;
73struct timespec __xtime __section_xtime;
74struct timezone __sys_tz __section_sys_tz;
75
1da177e4
LT
76/*
77 * do_gettimeoffset() returns microseconds since last timer interrupt was
78 * triggered by hardware. A memory read of HPET is slower than a register read
79 * of TSC, but much more reliable. It's also synchronized to the timer
80 * interrupt. Note that do_gettimeoffset() may return more than hpet_tick, if a
81 * timer interrupt has happened already, but vxtime.trigger wasn't updated yet.
82 * This is not a problem, because jiffies hasn't updated either. They are bound
83 * together by xtime_lock.
84 */
85
86static inline unsigned int do_gettimeoffset_tsc(void)
87{
88 unsigned long t;
89 unsigned long x;
c818a181 90 t = get_cycles_sync();
7351c0bf
AK
91 if (t < vxtime.last_tsc)
92 t = vxtime.last_tsc; /* hack */
1da177e4
LT
93 x = ((t - vxtime.last_tsc) * vxtime.tsc_quot) >> 32;
94 return x;
95}
96
97static inline unsigned int do_gettimeoffset_hpet(void)
98{
a3a00751 99 /* cap counter read to one tick to avoid inconsistencies */
100 unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
101 return (min(counter,hpet_tick) * vxtime.quot) >> 32;
1da177e4
LT
102}
103
104unsigned int (*do_gettimeoffset)(void) = do_gettimeoffset_tsc;
105
106/*
107 * This version of gettimeofday() has microsecond resolution and better than
108 * microsecond precision, as we're using at least a 10 MHz (usually 14.31818
109 * MHz) HPET timer.
110 */
111
112void do_gettimeofday(struct timeval *tv)
113{
114 unsigned long seq, t;
115 unsigned int sec, usec;
116
117 do {
118 seq = read_seqbegin(&xtime_lock);
119
120 sec = xtime.tv_sec;
121 usec = xtime.tv_nsec / 1000;
122
123 /* i386 does some correction here to keep the clock
124 monotonous even when ntpd is fixing drift.
125 But they didn't work for me, there is a non monotonic
126 clock anyways with ntp.
127 I dropped all corrections now until a real solution can
128 be found. Note when you fix it here you need to do the same
129 in arch/x86_64/kernel/vsyscall.c and export all needed
130 variables in vmlinux.lds. -AK */
131
132 t = (jiffies - wall_jiffies) * (1000000L / HZ) +
133 do_gettimeoffset();
134 usec += t;
135
136 } while (read_seqretry(&xtime_lock, seq));
137
138 tv->tv_sec = sec + usec / 1000000;
139 tv->tv_usec = usec % 1000000;
140}
141
142EXPORT_SYMBOL(do_gettimeofday);
143
144/*
145 * settimeofday() first undoes the correction that gettimeofday would do
146 * on the time, and then saves it. This is ugly, but has been like this for
147 * ages already.
148 */
149
150int do_settimeofday(struct timespec *tv)
151{
152 time_t wtm_sec, sec = tv->tv_sec;
153 long wtm_nsec, nsec = tv->tv_nsec;
154
155 if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
156 return -EINVAL;
157
158 write_seqlock_irq(&xtime_lock);
159
160 nsec -= do_gettimeoffset() * 1000 +
161 (jiffies - wall_jiffies) * (NSEC_PER_SEC/HZ);
162
163 wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
164 wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
165
166 set_normalized_timespec(&xtime, sec, nsec);
167 set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
168
b149ee22 169 ntp_clear();
1da177e4
LT
170
171 write_sequnlock_irq(&xtime_lock);
172 clock_was_set();
173 return 0;
174}
175
176EXPORT_SYMBOL(do_settimeofday);
177
178unsigned long profile_pc(struct pt_regs *regs)
179{
180 unsigned long pc = instruction_pointer(regs);
181
7351c0bf
AK
182 /* Assume the lock function has either no stack frame or only a single
183 word. This checks if the address on the stack looks like a kernel
184 text address.
1da177e4
LT
185 There is a small window for false hits, but in that case the tick
186 is just accounted to the spinlock function.
187 Better would be to write these functions in assembler again
188 and check exactly. */
189 if (in_lock_functions(pc)) {
190 char *v = *(char **)regs->rsp;
191 if ((v >= _stext && v <= _etext) ||
192 (v >= _sinittext && v <= _einittext) ||
193 (v >= (char *)MODULES_VADDR && v <= (char *)MODULES_END))
194 return (unsigned long)v;
195 return ((unsigned long *)regs->rsp)[1];
196 }
197 return pc;
198}
199EXPORT_SYMBOL(profile_pc);
200
201/*
202 * In order to set the CMOS clock precisely, set_rtc_mmss has to be called 500
203 * ms after the second nowtime has started, because when nowtime is written
204 * into the registers of the CMOS clock, it will jump to the next second
205 * precisely 500 ms later. Check the Motorola MC146818A or Dallas DS12887 data
206 * sheet for details.
207 */
208
209static void set_rtc_mmss(unsigned long nowtime)
210{
211 int real_seconds, real_minutes, cmos_minutes;
212 unsigned char control, freq_select;
213
214/*
215 * IRQs are disabled when we're called from the timer interrupt,
216 * no need for spin_lock_irqsave()
217 */
218
219 spin_lock(&rtc_lock);
220
221/*
222 * Tell the clock it's being set and stop it.
223 */
224
225 control = CMOS_READ(RTC_CONTROL);
226 CMOS_WRITE(control | RTC_SET, RTC_CONTROL);
227
228 freq_select = CMOS_READ(RTC_FREQ_SELECT);
229 CMOS_WRITE(freq_select | RTC_DIV_RESET2, RTC_FREQ_SELECT);
230
231 cmos_minutes = CMOS_READ(RTC_MINUTES);
232 BCD_TO_BIN(cmos_minutes);
233
234/*
235 * since we're only adjusting minutes and seconds, don't interfere with hour
236 * overflow. This avoids messing with unknown time zones but requires your RTC
237 * not to be off by more than 15 minutes. Since we're calling it only when
238 * our clock is externally synchronized using NTP, this shouldn't be a problem.
239 */
240
241 real_seconds = nowtime % 60;
242 real_minutes = nowtime / 60;
243 if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
244 real_minutes += 30; /* correct for half hour time zone */
245 real_minutes %= 60;
246
1da177e4
LT
247 if (abs(real_minutes - cmos_minutes) >= 30) {
248 printk(KERN_WARNING "time.c: can't update CMOS clock "
249 "from %d to %d\n", cmos_minutes, real_minutes);
28456ede 250 } else {
0b91317e
AK
251 BIN_TO_BCD(real_seconds);
252 BIN_TO_BCD(real_minutes);
1da177e4
LT
253 CMOS_WRITE(real_seconds, RTC_SECONDS);
254 CMOS_WRITE(real_minutes, RTC_MINUTES);
255 }
256
257/*
258 * The following flags have to be released exactly in this order, otherwise the
259 * DS12887 (popular MC146818A clone with integrated battery and quartz) will
260 * not reset the oscillator and will not update precisely 500 ms later. You
261 * won't find this mentioned in the Dallas Semiconductor data sheets, but who
262 * believes data sheets anyway ... -- Markus Kuhn
263 */
264
265 CMOS_WRITE(control, RTC_CONTROL);
266 CMOS_WRITE(freq_select, RTC_FREQ_SELECT);
267
268 spin_unlock(&rtc_lock);
269}
270
271
272/* monotonic_clock(): returns # of nanoseconds passed since time_init()
273 * Note: This function is required to return accurate
274 * time even in the absence of multiple timer ticks.
275 */
276unsigned long long monotonic_clock(void)
277{
278 unsigned long seq;
279 u32 last_offset, this_offset, offset;
280 unsigned long long base;
281
282 if (vxtime.mode == VXTIME_HPET) {
283 do {
284 seq = read_seqbegin(&xtime_lock);
285
286 last_offset = vxtime.last;
287 base = monotonic_base;
a3a00751 288 this_offset = hpet_readl(HPET_COUNTER);
1da177e4
LT
289 } while (read_seqretry(&xtime_lock, seq));
290 offset = (this_offset - last_offset);
7351c0bf 291 offset *= (NSEC_PER_SEC/HZ) / hpet_tick;
0b91317e 292 } else {
1da177e4
LT
293 do {
294 seq = read_seqbegin(&xtime_lock);
295
296 last_offset = vxtime.last_tsc;
297 base = monotonic_base;
298 } while (read_seqretry(&xtime_lock, seq));
c818a181 299 this_offset = get_cycles_sync();
7351c0bf 300 offset = (this_offset - last_offset)*1000 / cpu_khz;
1da177e4 301 }
7351c0bf 302 return base + offset;
1da177e4
LT
303}
304EXPORT_SYMBOL(monotonic_clock);
305
306static noinline void handle_lost_ticks(int lost, struct pt_regs *regs)
307{
7351c0bf
AK
308 static long lost_count;
309 static int warned;
310 if (report_lost_ticks) {
311 printk(KERN_WARNING "time.c: Lost %d timer tick(s)! ", lost);
312 print_symbol("rip %s)\n", regs->rip);
313 }
314
315 if (lost_count == 1000 && !warned) {
316 printk(KERN_WARNING "warning: many lost ticks.\n"
317 KERN_WARNING "Your time source seems to be instable or "
1da177e4 318 "some driver is hogging interupts\n");
7351c0bf
AK
319 print_symbol("rip %s\n", regs->rip);
320 if (vxtime.mode == VXTIME_TSC && vxtime.hpet_address) {
321 printk(KERN_WARNING "Falling back to HPET\n");
322 if (hpet_use_timer)
323 vxtime.last = hpet_readl(HPET_T0_CMP) -
324 hpet_tick;
325 else
326 vxtime.last = hpet_readl(HPET_COUNTER);
327 vxtime.mode = VXTIME_HPET;
328 do_gettimeoffset = do_gettimeoffset_hpet;
329 }
330 /* else should fall back to PIT, but code missing. */
331 warned = 1;
332 } else
333 lost_count++;
1da177e4
LT
334
335#ifdef CONFIG_CPU_FREQ
7351c0bf
AK
336 /* In some cases the CPU can change frequency without us noticing
337 Give cpufreq a change to catch up. */
338 if ((lost_count+1) % 25 == 0)
339 cpufreq_delayed_get();
1da177e4
LT
340#endif
341}
342
73dea47f 343void main_timer_handler(struct pt_regs *regs)
1da177e4
LT
344{
345 static unsigned long rtc_update = 0;
346 unsigned long tsc;
9ede6b09 347 int delay = 0, offset = 0, lost = 0;
1da177e4
LT
348
349/*
350 * Here we are in the timer irq handler. We have irqs locally disabled (so we
351 * don't need spin_lock_irqsave()) but we don't know if the timer_bh is running
352 * on the other CPU, so we need a lock. We also need to lock the vsyscall
353 * variables, because both do_timer() and us change them -arca+vojtech
354 */
355
356 write_seqlock(&xtime_lock);
357
a3a00751 358 if (vxtime.hpet_address)
359 offset = hpet_readl(HPET_COUNTER);
360
361 if (hpet_use_timer) {
362 /* if we're using the hpet timer functionality,
363 * we can more accurately know the counter value
364 * when the timer interrupt occured.
365 */
1da177e4
LT
366 offset = hpet_readl(HPET_T0_CMP) - hpet_tick;
367 delay = hpet_readl(HPET_COUNTER) - offset;
9ede6b09 368 } else if (!pmtmr_ioport) {
1da177e4
LT
369 spin_lock(&i8253_lock);
370 outb_p(0x00, 0x43);
371 delay = inb_p(0x40);
372 delay |= inb(0x40) << 8;
373 spin_unlock(&i8253_lock);
374 delay = LATCH - 1 - delay;
375 }
376
c818a181 377 tsc = get_cycles_sync();
1da177e4
LT
378
379 if (vxtime.mode == VXTIME_HPET) {
380 if (offset - vxtime.last > hpet_tick) {
381 lost = (offset - vxtime.last) / hpet_tick - 1;
382 }
383
384 monotonic_base +=
385 (offset - vxtime.last)*(NSEC_PER_SEC/HZ) / hpet_tick;
386
387 vxtime.last = offset;
312df5f1
AK
388#ifdef CONFIG_X86_PM_TIMER
389 } else if (vxtime.mode == VXTIME_PMTMR) {
390 lost = pmtimer_mark_offset();
391#endif
1da177e4
LT
392 } else {
393 offset = (((tsc - vxtime.last_tsc) *
394 vxtime.tsc_quot) >> 32) - (USEC_PER_SEC / HZ);
395
396 if (offset < 0)
397 offset = 0;
398
399 if (offset > (USEC_PER_SEC / HZ)) {
400 lost = offset / (USEC_PER_SEC / HZ);
401 offset %= (USEC_PER_SEC / HZ);
402 }
403
404 monotonic_base += (tsc - vxtime.last_tsc)*1000000/cpu_khz ;
405
406 vxtime.last_tsc = tsc - vxtime.quot * delay / vxtime.tsc_quot;
407
408 if ((((tsc - vxtime.last_tsc) *
409 vxtime.tsc_quot) >> 32) < offset)
410 vxtime.last_tsc = tsc -
411 (((long) offset << 32) / vxtime.tsc_quot) - 1;
412 }
413
414 if (lost > 0) {
415 handle_lost_ticks(lost, regs);
416 jiffies += lost;
417 }
418
419/*
420 * Do the timer stuff.
421 */
422
423 do_timer(regs);
424#ifndef CONFIG_SMP
425 update_process_times(user_mode(regs));
426#endif
427
428/*
429 * In the SMP case we use the local APIC timer interrupt to do the profiling,
430 * except when we simulate SMP mode on a uniprocessor system, in that case we
431 * have to call the local interrupt handler.
432 */
433
434#ifndef CONFIG_X86_LOCAL_APIC
435 profile_tick(CPU_PROFILING, regs);
436#else
437 if (!using_apic_timer)
438 smp_local_timer_interrupt(regs);
439#endif
440
441/*
442 * If we have an externally synchronized Linux clock, then update CMOS clock
443 * accordingly every ~11 minutes. set_rtc_mmss() will be called in the jiffy
444 * closest to exactly 500 ms before the next second. If the update fails, we
445 * don't care, as it'll be updated on the next turn, and the problem (time way
446 * off) isn't likely to go away much sooner anyway.
447 */
448
b149ee22 449 if (ntp_synced() && xtime.tv_sec > rtc_update &&
1da177e4
LT
450 abs(xtime.tv_nsec - 500000000) <= tick_nsec / 2) {
451 set_rtc_mmss(xtime.tv_sec);
452 rtc_update = xtime.tv_sec + 660;
453 }
454
455 write_sequnlock(&xtime_lock);
73dea47f 456}
1da177e4 457
73dea47f
AK
458static irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
459{
460 if (apic_runs_main_timer > 1)
461 return IRQ_HANDLED;
462 main_timer_handler(regs);
d25bf7e5
VP
463#ifdef CONFIG_X86_LOCAL_APIC
464 if (using_apic_timer)
465 smp_send_timer_broadcast_ipi();
466#endif
1da177e4
LT
467 return IRQ_HANDLED;
468}
469
68ed0040 470static unsigned int cyc2ns_scale __read_mostly;
1da177e4
LT
471#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
472
dacb16b1 473static inline void set_cyc2ns_scale(unsigned long cpu_khz)
1da177e4 474{
dacb16b1 475 cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
1da177e4
LT
476}
477
478static inline unsigned long long cycles_2_ns(unsigned long long cyc)
479{
480 return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
481}
482
483unsigned long long sched_clock(void)
484{
485 unsigned long a = 0;
486
487#if 0
488 /* Don't do a HPET read here. Using TSC always is much faster
489 and HPET may not be mapped yet when the scheduler first runs.
490 Disadvantage is a small drift between CPUs in some configurations,
491 but that should be tolerable. */
492 if (__vxtime.mode == VXTIME_HPET)
493 return (hpet_readl(HPET_COUNTER) * vxtime.quot) >> 32;
494#endif
495
496 /* Could do CPU core sync here. Opteron can execute rdtsc speculatively,
497 which means it is not completely exact and may not be monotonous between
498 CPUs. But the errors should be too small to matter for scheduling
499 purposes. */
500
501 rdtscll(a);
502 return cycles_2_ns(a);
503}
504
bdf2b1c9 505static unsigned long get_cmos_time(void)
1da177e4 506{
641f71f5 507 unsigned int year, mon, day, hour, min, sec;
1da177e4 508 unsigned long flags;
6954bee8 509 unsigned extyear = 0;
1da177e4 510
1da177e4
LT
511 spin_lock_irqsave(&rtc_lock, flags);
512
641f71f5
MM
513 do {
514 sec = CMOS_READ(RTC_SECONDS);
515 min = CMOS_READ(RTC_MINUTES);
516 hour = CMOS_READ(RTC_HOURS);
517 day = CMOS_READ(RTC_DAY_OF_MONTH);
518 mon = CMOS_READ(RTC_MONTH);
519 year = CMOS_READ(RTC_YEAR);
6954bee8 520#ifdef CONFIG_ACPI
641f71f5
MM
521 if (acpi_fadt.revision >= FADT2_REVISION_ID &&
522 acpi_fadt.century)
523 extyear = CMOS_READ(acpi_fadt.century);
6954bee8 524#endif
641f71f5 525 } while (sec != CMOS_READ(RTC_SECONDS));
6954bee8 526
1da177e4
LT
527 spin_unlock_irqrestore(&rtc_lock, flags);
528
0b91317e
AK
529 /*
530 * We know that x86-64 always uses BCD format, no need to check the
531 * config register.
7351c0bf 532 */
1da177e4 533
0b91317e
AK
534 BCD_TO_BIN(sec);
535 BCD_TO_BIN(min);
536 BCD_TO_BIN(hour);
537 BCD_TO_BIN(day);
538 BCD_TO_BIN(mon);
539 BCD_TO_BIN(year);
1da177e4 540
6954bee8
AK
541 if (extyear) {
542 BCD_TO_BIN(extyear);
543 year += extyear;
544 printk(KERN_INFO "Extended CMOS year: %d\n", extyear);
545 } else {
546 /*
547 * x86-64 systems only exists since 2002.
548 * This will work up to Dec 31, 2100
549 */
550 year += 2000;
551 }
1da177e4
LT
552
553 return mktime(year, mon, day, hour, min, sec);
554}
555
556#ifdef CONFIG_CPU_FREQ
557
558/* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
559 changes.
560
561 RED-PEN: On SMP we assume all CPUs run with the same frequency. It's
562 not that important because current Opteron setups do not support
563 scaling on SMP anyroads.
564
565 Should fix up last_tsc too. Currently gettimeofday in the
566 first tick after the change will be slightly wrong. */
567
568#include <linux/workqueue.h>
569
570static unsigned int cpufreq_delayed_issched = 0;
571static unsigned int cpufreq_init = 0;
572static struct work_struct cpufreq_delayed_get_work;
573
574static void handle_cpufreq_delayed_get(void *v)
575{
576 unsigned int cpu;
577 for_each_online_cpu(cpu) {
578 cpufreq_get(cpu);
579 }
580 cpufreq_delayed_issched = 0;
581}
582
583/* if we notice lost ticks, schedule a call to cpufreq_get() as it tries
584 * to verify the CPU frequency the timing core thinks the CPU is running
585 * at is still correct.
586 */
587static void cpufreq_delayed_get(void)
588{
589 static int warned;
590 if (cpufreq_init && !cpufreq_delayed_issched) {
591 cpufreq_delayed_issched = 1;
592 if (!warned) {
593 warned = 1;
7351c0bf
AK
594 printk(KERN_DEBUG
595 "Losing some ticks... checking if CPU frequency changed.\n");
1da177e4
LT
596 }
597 schedule_work(&cpufreq_delayed_get_work);
598 }
599}
600
601static unsigned int ref_freq = 0;
602static unsigned long loops_per_jiffy_ref = 0;
603
604static unsigned long cpu_khz_ref = 0;
605
606static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
607 void *data)
608{
609 struct cpufreq_freqs *freq = data;
610 unsigned long *lpj, dummy;
611
c29601e9
AK
612 if (cpu_has(&cpu_data[freq->cpu], X86_FEATURE_CONSTANT_TSC))
613 return 0;
614
1da177e4
LT
615 lpj = &dummy;
616 if (!(freq->flags & CPUFREQ_CONST_LOOPS))
617#ifdef CONFIG_SMP
7351c0bf 618 lpj = &cpu_data[freq->cpu].loops_per_jiffy;
1da177e4 619#else
7351c0bf 620 lpj = &boot_cpu_data.loops_per_jiffy;
1da177e4
LT
621#endif
622
1da177e4
LT
623 if (!ref_freq) {
624 ref_freq = freq->old;
625 loops_per_jiffy_ref = *lpj;
626 cpu_khz_ref = cpu_khz;
627 }
628 if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
629 (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
630 (val == CPUFREQ_RESUMECHANGE)) {
631 *lpj =
632 cpufreq_scale(loops_per_jiffy_ref, ref_freq, freq->new);
633
634 cpu_khz = cpufreq_scale(cpu_khz_ref, ref_freq, freq->new);
635 if (!(freq->flags & CPUFREQ_CONST_LOOPS))
636 vxtime.tsc_quot = (1000L << 32) / cpu_khz;
637 }
638
dacb16b1 639 set_cyc2ns_scale(cpu_khz_ref);
1da177e4
LT
640
641 return 0;
642}
643
644static struct notifier_block time_cpufreq_notifier_block = {
645 .notifier_call = time_cpufreq_notifier
646};
647
648static int __init cpufreq_tsc(void)
649{
650 INIT_WORK(&cpufreq_delayed_get_work, handle_cpufreq_delayed_get, NULL);
651 if (!cpufreq_register_notifier(&time_cpufreq_notifier_block,
652 CPUFREQ_TRANSITION_NOTIFIER))
653 cpufreq_init = 1;
654 return 0;
655}
656
657core_initcall(cpufreq_tsc);
658
659#endif
660
661/*
662 * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing
663 * it to the HPET timer of known frequency.
664 */
665
666#define TICK_COUNT 100000000
667
668static unsigned int __init hpet_calibrate_tsc(void)
669{
670 int tsc_start, hpet_start;
671 int tsc_now, hpet_now;
672 unsigned long flags;
673
674 local_irq_save(flags);
675 local_irq_disable();
676
677 hpet_start = hpet_readl(HPET_COUNTER);
678 rdtscl(tsc_start);
679
680 do {
681 local_irq_disable();
682 hpet_now = hpet_readl(HPET_COUNTER);
c818a181 683 tsc_now = get_cycles_sync();
1da177e4
LT
684 local_irq_restore(flags);
685 } while ((tsc_now - tsc_start) < TICK_COUNT &&
686 (hpet_now - hpet_start) < TICK_COUNT);
687
688 return (tsc_now - tsc_start) * 1000000000L
689 / ((hpet_now - hpet_start) * hpet_period / 1000);
690}
691
692
693/*
694 * pit_calibrate_tsc() uses the speaker output (channel 2) of
695 * the PIT. This is better than using the timer interrupt output,
696 * because we can read the value of the speaker with just one inb(),
697 * where we need three i/o operations for the interrupt channel.
698 * We count how many ticks the TSC does in 50 ms.
699 */
700
701static unsigned int __init pit_calibrate_tsc(void)
702{
703 unsigned long start, end;
704 unsigned long flags;
705
706 spin_lock_irqsave(&i8253_lock, flags);
707
708 outb((inb(0x61) & ~0x02) | 0x01, 0x61);
709
710 outb(0xb0, 0x43);
711 outb((PIT_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
712 outb((PIT_TICK_RATE / (1000 / 50)) >> 8, 0x42);
c818a181 713 start = get_cycles_sync();
1da177e4 714 while ((inb(0x61) & 0x20) == 0);
c818a181 715 end = get_cycles_sync();
1da177e4
LT
716
717 spin_unlock_irqrestore(&i8253_lock, flags);
718
719 return (end - start) / 50;
720}
721
722#ifdef CONFIG_HPET
723static __init int late_hpet_init(void)
724{
725 struct hpet_data hd;
726 unsigned int ntimer;
727
728 if (!vxtime.hpet_address)
3d34ee68 729 return 0;
1da177e4
LT
730
731 memset(&hd, 0, sizeof (hd));
732
733 ntimer = hpet_readl(HPET_ID);
734 ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
735 ntimer++;
736
737 /*
738 * Register with driver.
739 * Timer0 and Timer1 is used by platform.
740 */
741 hd.hd_phys_address = vxtime.hpet_address;
dd42b151 742 hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
1da177e4
LT
743 hd.hd_nirqs = ntimer;
744 hd.hd_flags = HPET_DATA_PLATFORM;
745 hpet_reserve_timer(&hd, 0);
746#ifdef CONFIG_HPET_EMULATE_RTC
747 hpet_reserve_timer(&hd, 1);
748#endif
749 hd.hd_irq[0] = HPET_LEGACY_8254;
750 hd.hd_irq[1] = HPET_LEGACY_RTC;
751 if (ntimer > 2) {
752 struct hpet *hpet;
753 struct hpet_timer *timer;
754 int i;
755
756 hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
7351c0bf
AK
757 timer = &hpet->hpet_timers[2];
758 for (i = 2; i < ntimer; timer++, i++)
1da177e4
LT
759 hd.hd_irq[i] = (timer->hpet_config &
760 Tn_INT_ROUTE_CNF_MASK) >>
761 Tn_INT_ROUTE_CNF_SHIFT;
762
763 }
764
765 hpet_alloc(&hd);
766 return 0;
767}
768fs_initcall(late_hpet_init);
769#endif
770
771static int hpet_timer_stop_set_go(unsigned long tick)
772{
773 unsigned int cfg;
774
775/*
776 * Stop the timers and reset the main counter.
777 */
778
779 cfg = hpet_readl(HPET_CFG);
780 cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
781 hpet_writel(cfg, HPET_CFG);
782 hpet_writel(0, HPET_COUNTER);
783 hpet_writel(0, HPET_COUNTER + 4);
784
785/*
786 * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
787 * and period also hpet_tick.
788 */
a3a00751 789 if (hpet_use_timer) {
790 hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
1da177e4 791 HPET_TN_32BIT, HPET_T0_CFG);
a3a00751 792 hpet_writel(hpet_tick, HPET_T0_CMP);
793 hpet_writel(hpet_tick, HPET_T0_CMP); /* AK: why twice? */
794 cfg |= HPET_CFG_LEGACY;
795 }
1da177e4
LT
796/*
797 * Go!
798 */
799
a3a00751 800 cfg |= HPET_CFG_ENABLE;
1da177e4
LT
801 hpet_writel(cfg, HPET_CFG);
802
803 return 0;
804}
805
806static int hpet_init(void)
807{
808 unsigned int id;
809
810 if (!vxtime.hpet_address)
811 return -1;
812 set_fixmap_nocache(FIX_HPET_BASE, vxtime.hpet_address);
813 __set_fixmap(VSYSCALL_HPET, vxtime.hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
814
815/*
816 * Read the period, compute tick and quotient.
817 */
818
819 id = hpet_readl(HPET_ID);
820
a3a00751 821 if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
1da177e4
LT
822 return -1;
823
824 hpet_period = hpet_readl(HPET_PERIOD);
825 if (hpet_period < 100000 || hpet_period > 100000000)
826 return -1;
827
828 hpet_tick = (1000000000L * (USEC_PER_SEC / HZ) + hpet_period / 2) /
829 hpet_period;
830
a3a00751 831 hpet_use_timer = (id & HPET_ID_LEGSUP);
832
1da177e4
LT
833 return hpet_timer_stop_set_go(hpet_tick);
834}
835
836static int hpet_reenable(void)
837{
838 return hpet_timer_stop_set_go(hpet_tick);
839}
840
73dea47f
AK
841#define PIT_MODE 0x43
842#define PIT_CH0 0x40
843
844static void __init __pit_init(int val, u8 mode)
1da177e4
LT
845{
846 unsigned long flags;
847
848 spin_lock_irqsave(&i8253_lock, flags);
73dea47f
AK
849 outb_p(mode, PIT_MODE);
850 outb_p(val & 0xff, PIT_CH0); /* LSB */
851 outb_p(val >> 8, PIT_CH0); /* MSB */
1da177e4
LT
852 spin_unlock_irqrestore(&i8253_lock, flags);
853}
854
73dea47f
AK
855void __init pit_init(void)
856{
857 __pit_init(LATCH, 0x34); /* binary, mode 2, LSB/MSB, ch 0 */
858}
859
860void __init pit_stop_interrupt(void)
861{
862 __pit_init(0, 0x30); /* mode 0 */
863}
864
865void __init stop_timer_interrupt(void)
866{
867 char *name;
868 if (vxtime.hpet_address) {
869 name = "HPET";
870 hpet_timer_stop_set_go(0);
871 } else {
872 name = "PIT";
873 pit_stop_interrupt();
874 }
875 printk(KERN_INFO "timer: %s interrupt stopped.\n", name);
876}
877
1da177e4
LT
878int __init time_setup(char *str)
879{
880 report_lost_ticks = 1;
881 return 1;
882}
883
884static struct irqaction irq0 = {
885 timer_interrupt, SA_INTERRUPT, CPU_MASK_NONE, "timer", NULL, NULL
886};
887
1da177e4
LT
888void __init time_init(void)
889{
890 char *timename;
e8b91777 891 char *gtod;
1da177e4
LT
892
893#ifdef HPET_HACK_ENABLE_DANGEROUS
894 if (!vxtime.hpet_address) {
895 printk(KERN_WARNING "time.c: WARNING: Enabling HPET base "
896 "manually!\n");
897 outl(0x800038a0, 0xcf8);
898 outl(0xff000001, 0xcfc);
899 outl(0x800038a0, 0xcf8);
900 vxtime.hpet_address = inl(0xcfc) & 0xfffffffe;
901 printk(KERN_WARNING "time.c: WARNING: Enabled HPET "
902 "at %#lx.\n", vxtime.hpet_address);
903 }
904#endif
905 if (nohpet)
906 vxtime.hpet_address = 0;
907
908 xtime.tv_sec = get_cmos_time();
909 xtime.tv_nsec = 0;
910
911 set_normalized_timespec(&wall_to_monotonic,
912 -xtime.tv_sec, -xtime.tv_nsec);
913
a3a00751 914 if (!hpet_init())
7351c0bf 915 vxtime_hz = (1000000000000000L + hpet_period / 2) / hpet_period;
68e18891
AK
916 else
917 vxtime.hpet_address = 0;
a3a00751 918
919 if (hpet_use_timer) {
b20367a6
JH
920 /* set tick_nsec to use the proper rate for HPET */
921 tick_nsec = TICK_NSEC_HPET;
1da177e4
LT
922 cpu_khz = hpet_calibrate_tsc();
923 timename = "HPET";
312df5f1 924#ifdef CONFIG_X86_PM_TIMER
fd495471 925 } else if (pmtmr_ioport && !vxtime.hpet_address) {
312df5f1
AK
926 vxtime_hz = PM_TIMER_FREQUENCY;
927 timename = "PM";
928 pit_init();
929 cpu_khz = pit_calibrate_tsc();
930#endif
1da177e4
LT
931 } else {
932 pit_init();
933 cpu_khz = pit_calibrate_tsc();
934 timename = "PIT";
935 }
936
e8b91777
AK
937 vxtime.mode = VXTIME_TSC;
938 gtod = time_init_gtod();
939
940 printk(KERN_INFO "time.c: Using %ld.%06ld MHz WALL %s GTOD %s timer.\n",
941 vxtime_hz / 1000000, vxtime_hz % 1000000, timename, gtod);
1da177e4
LT
942 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
943 cpu_khz / 1000, cpu_khz % 1000);
1da177e4
LT
944 vxtime.quot = (1000000L << 32) / vxtime_hz;
945 vxtime.tsc_quot = (1000L << 32) / cpu_khz;
c818a181 946 vxtime.last_tsc = get_cycles_sync();
1da177e4
LT
947 setup_irq(0, &irq0);
948
dacb16b1 949 set_cyc2ns_scale(cpu_khz);
1da177e4
LT
950}
951
312df5f1
AK
952/*
953 * Make an educated guess if the TSC is trustworthy and synchronized
954 * over all CPUs.
955 */
396bd50f 956__cpuinit int unsynchronized_tsc(void)
312df5f1
AK
957{
958#ifdef CONFIG_SMP
959 if (oem_force_hpet_timer())
960 return 1;
961 /* Intel systems are normally all synchronized. Exceptions
962 are handled in the OEM check above. */
963 if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
964 return 0;
312df5f1
AK
965#endif
966 /* Assume multi socket systems are not synchronized */
737c5c3b 967 return num_present_cpus() > 1;
312df5f1
AK
968}
969
a8ab26fe 970/*
e8b91777 971 * Decide what mode gettimeofday should use.
a8ab26fe 972 */
e8b91777 973__init static char *time_init_gtod(void)
1da177e4
LT
974{
975 char *timetype;
976
312df5f1 977 if (unsynchronized_tsc())
1da177e4
LT
978 notsc = 1;
979 if (vxtime.hpet_address && notsc) {
a3a00751 980 timetype = hpet_use_timer ? "HPET" : "PIT/HPET";
33042a9f
CM
981 if (hpet_use_timer)
982 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
983 else
984 vxtime.last = hpet_readl(HPET_COUNTER);
1da177e4
LT
985 vxtime.mode = VXTIME_HPET;
986 do_gettimeoffset = do_gettimeoffset_hpet;
312df5f1
AK
987#ifdef CONFIG_X86_PM_TIMER
988 /* Using PM for gettimeofday is quite slow, but we have no other
989 choice because the TSC is too unreliable on some systems. */
990 } else if (pmtmr_ioport && !vxtime.hpet_address && notsc) {
991 timetype = "PM";
992 do_gettimeoffset = do_gettimeoffset_pm;
993 vxtime.mode = VXTIME_PMTMR;
994 sysctl_vsyscall = 0;
995 printk(KERN_INFO "Disabling vsyscall due to use of PM timer\n");
996#endif
1da177e4 997 } else {
a3a00751 998 timetype = hpet_use_timer ? "HPET/TSC" : "PIT/TSC";
1da177e4
LT
999 vxtime.mode = VXTIME_TSC;
1000 }
e8b91777 1001 return timetype;
1da177e4
LT
1002}
1003
1004__setup("report_lost_ticks", time_setup);
1005
1006static long clock_cmos_diff;
1007static unsigned long sleep_start;
1008
0b91317e
AK
1009/*
1010 * sysfs support for the timer.
1011 */
1012
0b9c33a7 1013static int timer_suspend(struct sys_device *dev, pm_message_t state)
1da177e4
LT
1014{
1015 /*
1016 * Estimate time zone so that set_time can update the clock
1017 */
1018 long cmos_time = get_cmos_time();
1019
1020 clock_cmos_diff = -cmos_time;
1021 clock_cmos_diff += get_seconds();
1022 sleep_start = cmos_time;
1023 return 0;
1024}
1025
1026static int timer_resume(struct sys_device *dev)
1027{
1028 unsigned long flags;
1029 unsigned long sec;
1030 unsigned long ctime = get_cmos_time();
1031 unsigned long sleep_length = (ctime - sleep_start) * HZ;
1032
1033 if (vxtime.hpet_address)
1034 hpet_reenable();
1035 else
1036 i8254_timer_resume();
1037
1038 sec = ctime + clock_cmos_diff;
1039 write_seqlock_irqsave(&xtime_lock,flags);
1040 xtime.tv_sec = sec;
1041 xtime.tv_nsec = 0;
0dd2ea9a
SL
1042 if (vxtime.mode == VXTIME_HPET) {
1043 if (hpet_use_timer)
1044 vxtime.last = hpet_readl(HPET_T0_CMP) - hpet_tick;
1045 else
1046 vxtime.last = hpet_readl(HPET_COUNTER);
1047#ifdef CONFIG_X86_PM_TIMER
1048 } else if (vxtime.mode == VXTIME_PMTMR) {
1049 pmtimer_resume();
1050#endif
1051 } else
1052 vxtime.last_tsc = get_cycles_sync();
1da177e4
LT
1053 write_sequnlock_irqrestore(&xtime_lock,flags);
1054 jiffies += sleep_length;
1055 wall_jiffies += sleep_length;
0dd2ea9a 1056 monotonic_base += sleep_length * (NSEC_PER_SEC/HZ);
8446f1d3 1057 touch_softlockup_watchdog();
1da177e4
LT
1058 return 0;
1059}
1060
1061static struct sysdev_class timer_sysclass = {
1062 .resume = timer_resume,
1063 .suspend = timer_suspend,
1064 set_kset_name("timer"),
1065};
1066
1da177e4
LT
1067/* XXX this driverfs stuff should probably go elsewhere later -john */
1068static struct sys_device device_timer = {
1069 .id = 0,
1070 .cls = &timer_sysclass,
1071};
1072
1073static int time_init_device(void)
1074{
1075 int error = sysdev_class_register(&timer_sysclass);
1076 if (!error)
1077 error = sysdev_register(&device_timer);
1078 return error;
1079}
1080
1081device_initcall(time_init_device);
1082
1083#ifdef CONFIG_HPET_EMULATE_RTC
1084/* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
1085 * is enabled, we support RTC interrupt functionality in software.
1086 * RTC has 3 kinds of interrupts:
1087 * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
1088 * is updated
1089 * 2) Alarm Interrupt - generate an interrupt at a specific time of day
1090 * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
1091 * 2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
1092 * (1) and (2) above are implemented using polling at a frequency of
1093 * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
1094 * overhead. (DEFAULT_RTC_INT_FREQ)
1095 * For (3), we use interrupts at 64Hz or user specified periodic
1096 * frequency, whichever is higher.
1097 */
1098#include <linux/rtc.h>
1099
1da177e4
LT
1100#define DEFAULT_RTC_INT_FREQ 64
1101#define RTC_NUM_INTS 1
1102
1103static unsigned long UIE_on;
1104static unsigned long prev_update_sec;
1105
1106static unsigned long AIE_on;
1107static struct rtc_time alarm_time;
1108
1109static unsigned long PIE_on;
1110static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ;
1111static unsigned long PIE_count;
1112
1113static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
7811fb8f 1114static unsigned int hpet_t1_cmp; /* cached comparator register */
1da177e4
LT
1115
1116int is_hpet_enabled(void)
1117{
1118 return vxtime.hpet_address != 0;
1119}
1120
1121/*
1122 * Timer 1 for RTC, we do not use periodic interrupt feature,
1123 * even if HPET supports periodic interrupts on Timer 1.
1124 * The reason being, to set up a periodic interrupt in HPET, we need to
1125 * stop the main counter. And if we do that everytime someone diables/enables
1126 * RTC, we will have adverse effect on main kernel timer running on Timer 0.
1127 * So, for the time being, simulate the periodic interrupt in software.
1128 *
1129 * hpet_rtc_timer_init() is called for the first time and during subsequent
1130 * interuppts reinit happens through hpet_rtc_timer_reinit().
1131 */
1132int hpet_rtc_timer_init(void)
1133{
1134 unsigned int cfg, cnt;
1135 unsigned long flags;
1136
1137 if (!is_hpet_enabled())
1138 return 0;
1139 /*
1140 * Set the counter 1 and enable the interrupts.
1141 */
1142 if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
1143 hpet_rtc_int_freq = PIE_freq;
1144 else
1145 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
1146
1147 local_irq_save(flags);
1148 cnt = hpet_readl(HPET_COUNTER);
1149 cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
1150 hpet_writel(cnt, HPET_T1_CMP);
7811fb8f 1151 hpet_t1_cmp = cnt;
1da177e4
LT
1152 local_irq_restore(flags);
1153
1154 cfg = hpet_readl(HPET_T1_CFG);
5f819949
CL
1155 cfg &= ~HPET_TN_PERIODIC;
1156 cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
1da177e4
LT
1157 hpet_writel(cfg, HPET_T1_CFG);
1158
1159 return 1;
1160}
1161
1162static void hpet_rtc_timer_reinit(void)
1163{
1164 unsigned int cfg, cnt;
1165
f00c96f3
CL
1166 if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
1167 cfg = hpet_readl(HPET_T1_CFG);
1168 cfg &= ~HPET_TN_ENABLE;
1169 hpet_writel(cfg, HPET_T1_CFG);
1da177e4 1170 return;
f00c96f3 1171 }
1da177e4
LT
1172
1173 if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
1174 hpet_rtc_int_freq = PIE_freq;
1175 else
1176 hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
1177
1178 /* It is more accurate to use the comparator value than current count.*/
7811fb8f 1179 cnt = hpet_t1_cmp;
1da177e4
LT
1180 cnt += hpet_tick*HZ/hpet_rtc_int_freq;
1181 hpet_writel(cnt, HPET_T1_CMP);
7811fb8f 1182 hpet_t1_cmp = cnt;
1da177e4
LT
1183}
1184
1185/*
1186 * The functions below are called from rtc driver.
1187 * Return 0 if HPET is not being used.
1188 * Otherwise do the necessary changes and return 1.
1189 */
1190int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
1191{
1192 if (!is_hpet_enabled())
1193 return 0;
1194
1195 if (bit_mask & RTC_UIE)
1196 UIE_on = 0;
1197 if (bit_mask & RTC_PIE)
1198 PIE_on = 0;
1199 if (bit_mask & RTC_AIE)
1200 AIE_on = 0;
1201
1202 return 1;
1203}
1204
1205int hpet_set_rtc_irq_bit(unsigned long bit_mask)
1206{
1207 int timer_init_reqd = 0;
1208
1209 if (!is_hpet_enabled())
1210 return 0;
1211
1212 if (!(PIE_on | AIE_on | UIE_on))
1213 timer_init_reqd = 1;
1214
1215 if (bit_mask & RTC_UIE) {
1216 UIE_on = 1;
1217 }
1218 if (bit_mask & RTC_PIE) {
1219 PIE_on = 1;
1220 PIE_count = 0;
1221 }
1222 if (bit_mask & RTC_AIE) {
1223 AIE_on = 1;
1224 }
1225
1226 if (timer_init_reqd)
1227 hpet_rtc_timer_init();
1228
1229 return 1;
1230}
1231
1232int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
1233{
1234 if (!is_hpet_enabled())
1235 return 0;
1236
1237 alarm_time.tm_hour = hrs;
1238 alarm_time.tm_min = min;
1239 alarm_time.tm_sec = sec;
1240
1241 return 1;
1242}
1243
1244int hpet_set_periodic_freq(unsigned long freq)
1245{
1246 if (!is_hpet_enabled())
1247 return 0;
1248
1249 PIE_freq = freq;
1250 PIE_count = 0;
1251
1252 return 1;
1253}
1254
1255int hpet_rtc_dropped_irq(void)
1256{
1257 if (!is_hpet_enabled())
1258 return 0;
1259
1260 return 1;
1261}
1262
1263irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1264{
1265 struct rtc_time curr_time;
1266 unsigned long rtc_int_flag = 0;
1267 int call_rtc_interrupt = 0;
1268
1269 hpet_rtc_timer_reinit();
1270
1271 if (UIE_on | AIE_on) {
1272 rtc_get_rtc_time(&curr_time);
1273 }
1274 if (UIE_on) {
1275 if (curr_time.tm_sec != prev_update_sec) {
1276 /* Set update int info, call real rtc int routine */
1277 call_rtc_interrupt = 1;
1278 rtc_int_flag = RTC_UF;
1279 prev_update_sec = curr_time.tm_sec;
1280 }
1281 }
1282 if (PIE_on) {
1283 PIE_count++;
1284 if (PIE_count >= hpet_rtc_int_freq/PIE_freq) {
1285 /* Set periodic int info, call real rtc int routine */
1286 call_rtc_interrupt = 1;
1287 rtc_int_flag |= RTC_PF;
1288 PIE_count = 0;
1289 }
1290 }
1291 if (AIE_on) {
1292 if ((curr_time.tm_sec == alarm_time.tm_sec) &&
1293 (curr_time.tm_min == alarm_time.tm_min) &&
1294 (curr_time.tm_hour == alarm_time.tm_hour)) {
1295 /* Set alarm int info, call real rtc int routine */
1296 call_rtc_interrupt = 1;
1297 rtc_int_flag |= RTC_AF;
1298 }
1299 }
1300 if (call_rtc_interrupt) {
1301 rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
1302 rtc_interrupt(rtc_int_flag, dev_id, regs);
1303 }
1304 return IRQ_HANDLED;
1305}
1306#endif
1307
1da177e4
LT
1308static int __init nohpet_setup(char *s)
1309{
1310 nohpet = 1;
9b41046c 1311 return 1;
1da177e4
LT
1312}
1313
1314__setup("nohpet", nohpet_setup);
1315
7fd67843 1316int __init notsc_setup(char *s)
1da177e4
LT
1317{
1318 notsc = 1;
9b41046c 1319 return 1;
1da177e4
LT
1320}
1321
1322__setup("notsc", notsc_setup);
This page took 0.461738 seconds and 5 git commands to generate.