diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2007-02-22 07:16:21 -0500 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2007-04-26 04:54:08 -0400 |
| commit | a58c9f3c1e929c3c323c26dbdafef46373a719d4 (patch) | |
| tree | 8e303abb0db77527623cfaaacb38d2814a963ef1 | |
| parent | de46c33745f5e2ad594c72f2cf5f490861b16ce1 (diff) | |
[SPARC64]: Synchronize RTC clock via timer just like x86.
Signed-off-by: David S. Miller <davem@davemloft.net>
| -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 |
