sparc: convert to arch_gettimeoffset()
[linux-2.6.git] / arch / sparc / kernel / time_32.c
index 5b2f595..0d4c09b 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/platform_device.h>
 
 #include <asm/oplib.h>
+#include <asm/timex.h>
 #include <asm/timer.h>
 #include <asm/system.h>
 #include <asm/irq.h>
@@ -51,7 +52,6 @@ DEFINE_SPINLOCK(rtc_lock);
 EXPORT_SYMBOL(rtc_lock);
 
 static int set_rtc_mmss(unsigned long);
-static int sbus_do_settimeofday(struct timespec *tv);
 
 unsigned long profile_pc(struct pt_regs *regs)
 {
@@ -76,6 +76,8 @@ EXPORT_SYMBOL(profile_pc);
 
 __volatile__ unsigned int *master_l10_counter;
 
+u32 (*do_arch_gettimeoffset)(void);
+
 /*
  * timer_interrupt() needs to keep up the real-time clock,
  * as well as call the "do_timer()" routine every clocktick
@@ -196,35 +198,14 @@ static int __init clock_init(void)
 {
        return of_register_driver(&clock_driver, &of_platform_bus_type);
 }
-
 /* Must be after subsys_initcall() so that busses are probed.  Must
  * be before device_initcall() because things like the RTC driver
  * need to see the clock registers.
  */
 fs_initcall(clock_init);
 
-static void __init sbus_time_init(void)
-{
-
-       BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
-       btfixup();
-
-       sparc_init_timers(timer_interrupt);
-}
-
-void __init time_init(void)
-{
-#ifdef CONFIG_PCI
-       extern void pci_time_init(void);
-       if (pcic_present()) {
-               pci_time_init();
-               return;
-       }
-#endif
-       sbus_time_init();
-}
 
-static inline unsigned long do_gettimeoffset(void)
+u32 sbus_do_gettimeoffset(void)
 {
        unsigned long val = *master_l10_counter;
        unsigned long usec = (val >> 10) & 0x1fffff;
@@ -233,86 +214,39 @@ static inline unsigned long do_gettimeoffset(void)
        if (val & 0x80000000)
                usec += 1000000 / HZ;
 
-       return usec;
+       return usec * 1000;
 }
 
-/* Ok, my cute asm atomicity trick doesn't work anymore.
- * There are just too many variables that need to be protected
- * now (both members of xtime, et al.)
- */
-void do_gettimeofday(struct timeval *tv)
-{
-       unsigned long flags;
-       unsigned long seq;
-       unsigned long usec, sec;
-       unsigned long max_ntp_tick = tick_usec - tickadj;
-
-       do {
-               seq = read_seqbegin_irqsave(&xtime_lock, flags);
-               usec = do_gettimeoffset();
-
-               /*
-                * If time_adjust is negative then NTP is slowing the clock
-                * so make sure not to go into next possible interval.
-                * Better to lose some accuracy than have time go backwards..
-                */
-               if (unlikely(time_adjust < 0))
-                       usec = min(usec, max_ntp_tick);
-
-               sec = xtime.tv_sec;
-               usec += (xtime.tv_nsec / 1000);
-       } while (read_seqretry_irqrestore(&xtime_lock, seq, flags));
-
-       while (usec >= 1000000) {
-               usec -= 1000000;
-               sec++;
-       }
 
-       tv->tv_sec = sec;
-       tv->tv_usec = usec;
-}
-
-EXPORT_SYMBOL(do_gettimeofday);
-
-int do_settimeofday(struct timespec *tv)
+u32 arch_gettimeoffset(void)
 {
-       int ret;
-
-       write_seqlock_irq(&xtime_lock);
-       ret = bus_do_settimeofday(tv);
-       write_sequnlock_irq(&xtime_lock);
-       clock_was_set();
-       return ret;
+       if (unlikely(!do_arch_gettimeoffset))
+               return 0;
+       return do_arch_gettimeoffset();
 }
 
-EXPORT_SYMBOL(do_settimeofday);
-
-static int sbus_do_settimeofday(struct timespec *tv)
+static void __init sbus_time_init(void)
 {
-       time_t wtm_sec, sec = tv->tv_sec;
-       long wtm_nsec, nsec = tv->tv_nsec;
+       do_arch_gettimeoffset = sbus_do_gettimeoffset;
 
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
-               return -EINVAL;
-
-       /*
-        * This is revolting. We need to set "xtime" correctly. However, the
-        * value in this location is the value at the most recent update of
-        * wall time.  Discover what correction gettimeofday() would have
-        * made, and then undo it!
-        */
-       nsec -= 1000 * do_gettimeoffset();
-
-       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
-       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+       btfixup();
 
-       set_normalized_timespec(&xtime, sec, nsec);
-       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+       sparc_init_timers(timer_interrupt);
+}
 
-       ntp_clear();
-       return 0;
+void __init time_init(void)
+{
+#ifdef CONFIG_PCI
+       extern void pci_time_init(void);
+       if (pcic_present()) {
+               pci_time_init();
+               return;
+       }
+#endif
+       sbus_time_init();
 }
 
+
 static int set_rtc_mmss(unsigned long secs)
 {
        struct rtc_device *rtc = rtc_class_open("rtc0");