diff options
Diffstat (limited to 'arch/sparc64/kernel/time.c')
-rw-r--r-- | arch/sparc64/kernel/time.c | 66 |
1 files changed, 48 insertions, 18 deletions
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index f84da4f1b706..d457079118dc 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -435,22 +435,56 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; | |||
435 | 435 | ||
436 | #define TICK_SIZE (tick_nsec / 1000) | 436 | #define TICK_SIZE (tick_nsec / 1000) |
437 | 437 | ||
438 | static inline void timer_check_rtc(void) | 438 | #define USEC_AFTER 500000 |
439 | #define USEC_BEFORE 500000 | ||
440 | |||
441 | static void sync_cmos_clock(unsigned long dummy); | ||
442 | |||
443 | static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0); | ||
444 | |||
445 | static void sync_cmos_clock(unsigned long dummy) | ||
439 | { | 446 | { |
440 | /* last time the cmos clock got updated */ | 447 | struct timeval now, next; |
441 | static long last_rtc_update; | 448 | int fail = 1; |
442 | 449 | ||
443 | /* Determine when to update the Mostek clock. */ | 450 | /* |
444 | if (ntp_synced() && | 451 | * If we have an externally synchronized Linux clock, then update |
445 | xtime.tv_sec > last_rtc_update + 660 && | 452 | * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be |
446 | (xtime.tv_nsec / 1000) >= 500000 - ((unsigned) TICK_SIZE) / 2 && | 453 | * called as close as possible to 500 ms before the new second starts. |
447 | (xtime.tv_nsec / 1000) <= 500000 + ((unsigned) TICK_SIZE) / 2) { | 454 | * This code is run on a timer. If the clock is set, that timer |
448 | if (set_rtc_mmss(xtime.tv_sec) == 0) | 455 | * may not expire at the correct time. Thus, we adjust... |
449 | last_rtc_update = xtime.tv_sec; | 456 | */ |
450 | else | 457 | if (!ntp_synced()) |
451 | last_rtc_update = xtime.tv_sec - 600; | 458 | /* |
452 | /* do it again in 60 s */ | 459 | * Not synced, exit, do not restart a timer (if one is |
460 | * running, let it run out). | ||
461 | */ | ||
462 | return; | ||
463 | |||
464 | do_gettimeofday(&now); | ||
465 | if (now.tv_usec >= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 && | ||
466 | now.tv_usec <= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) | ||
467 | fail = set_rtc_mmss(now.tv_sec); | ||
468 | |||
469 | next.tv_usec = USEC_AFTER - now.tv_usec; | ||
470 | if (next.tv_usec <= 0) | ||
471 | next.tv_usec += USEC_PER_SEC; | ||
472 | |||
473 | if (!fail) | ||
474 | next.tv_sec = 659; | ||
475 | else | ||
476 | next.tv_sec = 0; | ||
477 | |||
478 | if (next.tv_usec >= USEC_PER_SEC) { | ||
479 | next.tv_sec++; | ||
480 | next.tv_usec -= USEC_PER_SEC; | ||
453 | } | 481 | } |
482 | mod_timer(&sync_cmos_timer, jiffies + timeval_to_jiffies(&next)); | ||
483 | } | ||
484 | |||
485 | void notify_arch_cmos_timer(void) | ||
486 | { | ||
487 | mod_timer(&sync_cmos_timer, jiffies + 1); | ||
454 | } | 488 | } |
455 | 489 | ||
456 | irqreturn_t timer_interrupt(int irq, void *dev_id) | 490 | irqreturn_t timer_interrupt(int irq, void *dev_id) |
@@ -483,8 +517,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) | |||
483 | : "r" (pstate)); | 517 | : "r" (pstate)); |
484 | } while (time_after_eq(ticks, compare)); | 518 | } while (time_after_eq(ticks, compare)); |
485 | 519 | ||
486 | timer_check_rtc(); | ||
487 | |||
488 | write_sequnlock(&xtime_lock); | 520 | write_sequnlock(&xtime_lock); |
489 | 521 | ||
490 | return IRQ_HANDLED; | 522 | return IRQ_HANDLED; |
@@ -497,8 +529,6 @@ void timer_tick_interrupt(struct pt_regs *regs) | |||
497 | 529 | ||
498 | do_timer(1); | 530 | do_timer(1); |
499 | 531 | ||
500 | timer_check_rtc(); | ||
501 | |||
502 | write_sequnlock(&xtime_lock); | 532 | write_sequnlock(&xtime_lock); |
503 | } | 533 | } |
504 | #endif | 534 | #endif |