sparc: convert to arch_gettimeoffset()
[linux-2.6.git] / arch / sparc / kernel / pcic.c
index 85e7037..4e2724e 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/oplib.h>
 #include <asm/prom.h>
 #include <asm/pcic.h>
+#include <asm/timex.h>
 #include <asm/timer.h>
 #include <asm/uaccess.h>
 #include <asm/irq_regs.h>
@@ -163,8 +164,6 @@ void __iomem *pcic_regs;
 volatile int pcic_speculative;
 volatile int pcic_trapped;
 
-static void pci_do_gettimeofday(struct timeval *tv);
-static int pci_do_settimeofday(struct timespec *tv);
 
 #define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
 
@@ -716,19 +715,27 @@ static irqreturn_t pcic_timer_handler (int irq, void *h)
 #define USECS_PER_JIFFY  10000  /* We have 100HZ "standard" timer for sparc */
 #define TICK_TIMER_LIMIT ((100*1000000/4)/100)
 
+u32 pci_gettimeoffset(void)
+{
+       /*
+        * We divide all by 100
+        * to have microsecond resolution and to avoid overflow
+        */
+       unsigned long count =
+           readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
+       count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
+       return count * 1000;
+}
+
+
 void __init pci_time_init(void)
 {
        struct linux_pcic *pcic = &pcic0;
        unsigned long v;
        int timer_irq, irq;
 
-       /* A hack until do_gettimeofday prototype is moved to arch specific headers
-          and btfixupped. Patch do_gettimeofday with ba pci_do_gettimeofday; nop */
-       ((unsigned int *)do_gettimeofday)[0] = 
-           0x10800000 | ((((unsigned long)pci_do_gettimeofday -
-            (unsigned long)do_gettimeofday) >> 2) & 0x003fffff);
-       ((unsigned int *)do_gettimeofday)[1] = 0x01000000;
-       BTFIXUPSET_CALL(bus_do_settimeofday, pci_do_settimeofday, BTFIXUPCALL_NORM);
+       do_arch_gettimeoffset = pci_gettimeoffset;
+
        btfixup();
 
        writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT);
@@ -746,84 +753,6 @@ void __init pci_time_init(void)
        local_irq_enable();
 }
 
-static inline unsigned long do_gettimeoffset(void)
-{
-       /*
-        * We divide all by 100
-        * to have microsecond resolution and to avoid overflow
-        */
-       unsigned long count =
-           readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;
-       count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);
-       return count;
-}
-
-static void pci_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;
-}
-
-static int pci_do_settimeofday(struct timespec *tv)
-{
-       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!
-        */
-       tv->tv_nsec -= 1000 * do_gettimeoffset();
-       while (tv->tv_nsec < 0) {
-               tv->tv_nsec += NSEC_PER_SEC;
-               tv->tv_sec--;
-       }
-
-       wall_to_monotonic.tv_sec += xtime.tv_sec - tv->tv_sec;
-       wall_to_monotonic.tv_nsec += xtime.tv_nsec - tv->tv_nsec;
-
-       if (wall_to_monotonic.tv_nsec > NSEC_PER_SEC) {
-               wall_to_monotonic.tv_nsec -= NSEC_PER_SEC;
-               wall_to_monotonic.tv_sec++;
-       }
-       if (wall_to_monotonic.tv_nsec < 0) {
-               wall_to_monotonic.tv_nsec += NSEC_PER_SEC;
-               wall_to_monotonic.tv_sec--;
-       }
-
-       xtime.tv_sec = tv->tv_sec;
-       xtime.tv_nsec = tv->tv_nsec;
-       ntp_clear();
-       return 0;
-}
 
 #if 0
 static void watchdog_reset() {