diff options
-rw-r--r-- | arch/powerpc/kernel/time.c | 79 | ||||
-rw-r--r-- | include/asm-powerpc/time.h | 14 |
2 files changed, 69 insertions, 24 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index b635c7de6698..ad501d62aa6e 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -126,6 +126,16 @@ unsigned long ppc_tb_freq; | |||
126 | #define boot_cpuid 0 | 126 | #define boot_cpuid 0 |
127 | #endif | 127 | #endif |
128 | 128 | ||
129 | u64 tb_last_jiffy __cacheline_aligned_in_smp; | ||
130 | unsigned long tb_last_stamp; | ||
131 | |||
132 | /* | ||
133 | * Note that on ppc32 this only stores the bottom 32 bits of | ||
134 | * the timebase value, but that's enough to tell when a jiffy | ||
135 | * has passed. | ||
136 | */ | ||
137 | DEFINE_PER_CPU(unsigned long, last_jiffy); | ||
138 | |||
129 | static __inline__ void timer_check_rtc(void) | 139 | static __inline__ void timer_check_rtc(void) |
130 | { | 140 | { |
131 | /* | 141 | /* |
@@ -191,6 +201,26 @@ static inline void __do_gettimeofday(struct timeval *tv, u64 tb_val) | |||
191 | 201 | ||
192 | void do_gettimeofday(struct timeval *tv) | 202 | void do_gettimeofday(struct timeval *tv) |
193 | { | 203 | { |
204 | if (__USE_RTC()) { | ||
205 | /* do this the old way */ | ||
206 | unsigned long flags, seq; | ||
207 | unsigned int sec, nsec, usec, lost; | ||
208 | |||
209 | do { | ||
210 | seq = read_seqbegin_irqsave(&xtime_lock, flags); | ||
211 | sec = xtime.tv_sec; | ||
212 | nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp); | ||
213 | lost = jiffies - wall_jiffies; | ||
214 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | ||
215 | usec = nsec / 1000 + lost * (1000000 / HZ); | ||
216 | while (usec >= 1000000) { | ||
217 | usec -= 1000000; | ||
218 | ++sec; | ||
219 | } | ||
220 | tv->tv_sec = sec; | ||
221 | tv->tv_usec = usec; | ||
222 | return; | ||
223 | } | ||
194 | __do_gettimeofday(tv, get_tb()); | 224 | __do_gettimeofday(tv, get_tb()); |
195 | } | 225 | } |
196 | 226 | ||
@@ -272,6 +302,8 @@ static __inline__ void timer_recalc_offset(u64 cur_tb) | |||
272 | unsigned long offset; | 302 | unsigned long offset; |
273 | u64 new_stamp_xsec; | 303 | u64 new_stamp_xsec; |
274 | 304 | ||
305 | if (__USE_RTC()) | ||
306 | return; | ||
275 | offset = cur_tb - do_gtod.varp->tb_orig_stamp; | 307 | offset = cur_tb - do_gtod.varp->tb_orig_stamp; |
276 | if ((offset & 0x80000000u) == 0) | 308 | if ((offset & 0x80000000u) == 0) |
277 | return; | 309 | return; |
@@ -357,15 +389,6 @@ static void iSeries_tb_recal(void) | |||
357 | * call will not be needed) | 389 | * call will not be needed) |
358 | */ | 390 | */ |
359 | 391 | ||
360 | u64 tb_last_stamp __cacheline_aligned_in_smp; | ||
361 | |||
362 | /* | ||
363 | * Note that on ppc32 this only stores the bottom 32 bits of | ||
364 | * the timebase value, but that's enough to tell when a jiffy | ||
365 | * has passed. | ||
366 | */ | ||
367 | DEFINE_PER_CPU(unsigned long, last_jiffy); | ||
368 | |||
369 | /* | 392 | /* |
370 | * timer_interrupt - gets called when the decrementer overflows, | 393 | * timer_interrupt - gets called when the decrementer overflows, |
371 | * with interrupts disabled. | 394 | * with interrupts disabled. |
@@ -415,10 +438,11 @@ void timer_interrupt(struct pt_regs * regs) | |||
415 | continue; | 438 | continue; |
416 | 439 | ||
417 | write_seqlock(&xtime_lock); | 440 | write_seqlock(&xtime_lock); |
418 | tb_last_stamp += tb_ticks_per_jiffy; | 441 | tb_last_jiffy += tb_ticks_per_jiffy; |
419 | timer_recalc_offset(tb_last_stamp); | 442 | tb_last_stamp = per_cpu(last_jiffy, cpu); |
443 | timer_recalc_offset(tb_last_jiffy); | ||
420 | do_timer(regs); | 444 | do_timer(regs); |
421 | timer_sync_xtime(tb_last_stamp); | 445 | timer_sync_xtime(tb_last_jiffy); |
422 | timer_check_rtc(); | 446 | timer_check_rtc(); |
423 | write_sequnlock(&xtime_lock); | 447 | write_sequnlock(&xtime_lock); |
424 | if (adjusting_time && (time_adjust == 0)) | 448 | if (adjusting_time && (time_adjust == 0)) |
@@ -453,7 +477,7 @@ void wakeup_decrementer(void) | |||
453 | * We don't expect this to be called on a machine with a 601, | 477 | * We don't expect this to be called on a machine with a 601, |
454 | * so using get_tbl is fine. | 478 | * so using get_tbl is fine. |
455 | */ | 479 | */ |
456 | tb_last_stamp = get_tb(); | 480 | tb_last_stamp = tb_last_jiffy = get_tb(); |
457 | for_each_cpu(i) | 481 | for_each_cpu(i) |
458 | per_cpu(last_jiffy, i) = tb_last_stamp; | 482 | per_cpu(last_jiffy, i) = tb_last_stamp; |
459 | } | 483 | } |
@@ -483,6 +507,8 @@ void __init smp_space_timers(unsigned int max_cpus) | |||
483 | */ | 507 | */ |
484 | unsigned long long sched_clock(void) | 508 | unsigned long long sched_clock(void) |
485 | { | 509 | { |
510 | if (__USE_RTC()) | ||
511 | return get_rtc(); | ||
486 | return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift; | 512 | return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift; |
487 | } | 513 | } |
488 | 514 | ||
@@ -534,7 +560,7 @@ int do_settimeofday(struct timespec *tv) | |||
534 | new_xsec = (u64)new_nsec * XSEC_PER_SEC; | 560 | new_xsec = (u64)new_nsec * XSEC_PER_SEC; |
535 | do_div(new_xsec, NSEC_PER_SEC); | 561 | do_div(new_xsec, NSEC_PER_SEC); |
536 | new_xsec += (u64)new_sec * XSEC_PER_SEC; | 562 | new_xsec += (u64)new_sec * XSEC_PER_SEC; |
537 | update_gtod(tb_last_stamp, new_xsec, do_gtod.varp->tb_to_xs); | 563 | update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); |
538 | 564 | ||
539 | #ifdef CONFIG_PPC64 | 565 | #ifdef CONFIG_PPC64 |
540 | systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; | 566 | systemcfg->tz_minuteswest = sys_tz.tz_minuteswest; |
@@ -616,12 +642,20 @@ void __init time_init(void) | |||
616 | if (ppc_md.time_init != NULL) | 642 | if (ppc_md.time_init != NULL) |
617 | timezone_offset = ppc_md.time_init(); | 643 | timezone_offset = ppc_md.time_init(); |
618 | 644 | ||
619 | ppc_md.calibrate_decr(); | 645 | if (__USE_RTC()) { |
620 | 646 | /* 601 processor: dec counts down by 128 every 128ns */ | |
621 | printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", | 647 | ppc_tb_freq = 1000000000; |
622 | ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); | 648 | tb_last_stamp = get_rtcl(); |
623 | printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n", | 649 | tb_last_jiffy = tb_last_stamp; |
624 | ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); | 650 | } else { |
651 | /* Normal PowerPC with timebase register */ | ||
652 | ppc_md.calibrate_decr(); | ||
653 | printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
654 | ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); | ||
655 | printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n", | ||
656 | ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); | ||
657 | tb_last_stamp = tb_last_jiffy = get_tb(); | ||
658 | } | ||
625 | 659 | ||
626 | tb_ticks_per_jiffy = ppc_tb_freq / HZ; | 660 | tb_ticks_per_jiffy = ppc_tb_freq / HZ; |
627 | tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; | 661 | tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; |
@@ -661,17 +695,16 @@ void __init time_init(void) | |||
661 | write_seqlock_irqsave(&xtime_lock, flags); | 695 | write_seqlock_irqsave(&xtime_lock, flags); |
662 | xtime.tv_sec = tm; | 696 | xtime.tv_sec = tm; |
663 | xtime.tv_nsec = 0; | 697 | xtime.tv_nsec = 0; |
664 | tb_last_stamp = get_tb(); | ||
665 | do_gtod.varp = &do_gtod.vars[0]; | 698 | do_gtod.varp = &do_gtod.vars[0]; |
666 | do_gtod.var_idx = 0; | 699 | do_gtod.var_idx = 0; |
667 | do_gtod.varp->tb_orig_stamp = tb_last_stamp; | 700 | do_gtod.varp->tb_orig_stamp = tb_last_jiffy; |
668 | __get_cpu_var(last_jiffy) = tb_last_stamp; | 701 | __get_cpu_var(last_jiffy) = tb_last_stamp; |
669 | do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; | 702 | do_gtod.varp->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; |
670 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; | 703 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; |
671 | do_gtod.varp->tb_to_xs = tb_to_xs; | 704 | do_gtod.varp->tb_to_xs = tb_to_xs; |
672 | do_gtod.tb_to_us = tb_to_us; | 705 | do_gtod.tb_to_us = tb_to_us; |
673 | #ifdef CONFIG_PPC64 | 706 | #ifdef CONFIG_PPC64 |
674 | systemcfg->tb_orig_stamp = tb_last_stamp; | 707 | systemcfg->tb_orig_stamp = tb_last_jiffy; |
675 | systemcfg->tb_update_count = 0; | 708 | systemcfg->tb_update_count = 0; |
676 | systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; | 709 | systemcfg->tb_ticks_per_sec = tb_ticks_per_sec; |
677 | systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; | 710 | systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; |
diff --git a/include/asm-powerpc/time.h b/include/asm-powerpc/time.h index 99bfe3281768..410e795f7d43 100644 --- a/include/asm-powerpc/time.h +++ b/include/asm-powerpc/time.h | |||
@@ -30,7 +30,8 @@ extern unsigned long tb_ticks_per_usec; | |||
30 | extern unsigned long tb_ticks_per_sec; | 30 | extern unsigned long tb_ticks_per_sec; |
31 | extern u64 tb_to_xs; | 31 | extern u64 tb_to_xs; |
32 | extern unsigned tb_to_us; | 32 | extern unsigned tb_to_us; |
33 | extern u64 tb_last_stamp; | 33 | extern unsigned long tb_last_stamp; |
34 | extern u64 tb_last_jiffy; | ||
34 | 35 | ||
35 | DECLARE_PER_CPU(unsigned long, last_jiffy); | 36 | DECLARE_PER_CPU(unsigned long, last_jiffy); |
36 | 37 | ||
@@ -113,6 +114,17 @@ static inline unsigned int get_rtcl(void) | |||
113 | return rtcl; | 114 | return rtcl; |
114 | } | 115 | } |
115 | 116 | ||
117 | static inline u64 get_rtc(void) | ||
118 | { | ||
119 | unsigned int hi, lo, hi2; | ||
120 | |||
121 | do { | ||
122 | asm volatile("mfrtcu %0; mfrtcl %1; mfrtcu %2" | ||
123 | : "=r" (hi), "=r" (lo), "=r" (hi2)); | ||
124 | } while (hi2 != hi); | ||
125 | return (u64)hi * 1000000000 + lo; | ||
126 | } | ||
127 | |||
116 | #ifdef CONFIG_PPC64 | 128 | #ifdef CONFIG_PPC64 |
117 | static inline u64 get_tb(void) | 129 | static inline u64 get_tb(void) |
118 | { | 130 | { |