Add changes from the Linux-2.6 tree.
[linux-2.6.git] / arch / cris / kernel / time.c
index 9ca0f20..0f9213c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.9 2003/07/04 08:27:52 starvik Exp $
+/* $Id: time.c,v 1.18 2005/03/04 08:16:17 starvik Exp $
  *
  *  linux/arch/cris/kernel/time.c
  *
 #include <linux/jiffies.h>
 #include <linux/bcd.h>
 #include <linux/timex.h>
-
-u64 jiffies_64 = INITIAL_JIFFIES;
-
-EXPORT_SYMBOL(jiffies_64);
+#include <linux/init.h>
+#include <linux/profile.h>
+#include <linux/sched.h>       /* just for sched_clock() - funny that */
 
 int have_rtc;  /* used to remember if we have an RTC or not */;
 
 #define TICK_SIZE tick
 
-extern unsigned long wall_jiffies;
+extern unsigned long loops_per_jiffy; /* init/main.c */
+unsigned long loops_per_usec;
 
 extern unsigned long do_slow_gettimeoffset(void);
 static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
@@ -57,11 +57,15 @@ void do_gettimeofday(struct timeval *tv)
        local_irq_save(flags);
        local_irq_disable();
        usec = do_gettimeoffset();
-       {
-               unsigned long lost = jiffies - wall_jiffies;
-               if (lost)
-                       usec += lost * (1000000 / HZ);
-       }
+
+        /*
+        * 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 > tickadj)
+               usec = tickadj;
+
        sec = xtime.tv_sec;
        usec += xtime.tv_nsec / 1000;
        local_irq_restore(flags);
@@ -79,35 +83,29 @@ EXPORT_SYMBOL(do_gettimeofday);
 
 int do_settimeofday(struct timespec *tv)
 {
-       unsigned long flags;
+       time_t wtm_sec, sec = tv->tv_sec;
+       long wtm_nsec, nsec = tv->tv_nsec;
 
-        if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
                return -EINVAL;
 
-       local_irq_save(flags);
-       local_irq_disable();
-
-       /* This is revolting. We need to set the xtime.tv_usec
-        * correctly. However, the value in this location is
-        * is value at the last tick.
-        * Discover what correction gettimeofday
-        * would have done, and then undo it!
+       write_seqlock_irq(&xtime_lock);
+       /*
+        * 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 -= do_gettimeoffset() * 1000;
-        tv->tv_nsec -= (jiffies - wall_jiffies) * TICK_NSEC;
+       nsec -= do_gettimeoffset() * NSEC_PER_USEC;
 
-       while (tv->tv_nsec < 0) {
-               tv->tv_nsec += NSEC_PER_SEC;
-               tv->tv_sec--;
-       }
-       xtime.tv_sec = tv->tv_sec;
-       xtime.tv_nsec = tv->tv_nsec;
-       time_adjust = 0;                /* stop active adjtime() */
-       time_status |= STA_UNSYNC;
-       time_state = TIME_ERROR;        /* p. 24, (a) */
-       time_maxerror = NTP_PHASE_LIMIT;
-       time_esterror = NTP_PHASE_LIMIT;
-       local_irq_restore(flags);
+       wtm_sec  = wall_to_monotonic.tv_sec + (xtime.tv_sec - sec);
+       wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - nsec);
+
+       set_normalized_timespec(&xtime, sec, nsec);
+       set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec);
+
+       ntp_clear();
+       write_sequnlock_irq(&xtime_lock);
        clock_was_set();
        return 0;
 }
@@ -125,7 +123,7 @@ int set_rtc_mmss(unsigned long nowtime)
        int retval = 0;
        int real_seconds, real_minutes, cmos_minutes;
 
-       printk("set_rtc_mmss(%lu)\n", nowtime);
+       printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime);
 
        if(!have_rtc)
                return 0;
@@ -174,7 +172,8 @@ get_cmos_time(void)
        mon = CMOS_READ(RTC_MONTH);
        year = CMOS_READ(RTC_YEAR);
 
-       printk("rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n", 
+       printk(KERN_DEBUG
+              "rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n",
               sec, min, hour, day, mon, year);
 
        BCD_TO_BIN(sec);
@@ -202,3 +201,35 @@ update_xtime_from_cmos(void)
                xtime.tv_nsec = 0;
        }
 }
+
+extern void cris_profile_sample(struct pt_regs* regs);
+
+void
+cris_do_profile(struct pt_regs* regs)
+{
+
+#if CONFIG_SYSTEM_PROFILER
+        cris_profile_sample(regs);
+#endif
+
+#if CONFIG_PROFILING
+        profile_tick(CPU_PROFILING, regs);
+#endif
+}
+
+/*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+       return (unsigned long long)jiffies * (1000000000 / HZ);
+}
+
+static int
+__init init_udelay(void)
+{
+       loops_per_usec = (loops_per_jiffy * HZ) / 1000000;
+       return 0;
+}
+
+__initcall(init_udelay);