Merge branch 'next' of ../next
[platform/kernel/u-boot.git] / lib_sh / time.c
index 2bd7715..9a8f89a 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * (C) Copyright 2009
+ * Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
  * (C) Copyright 2007-2008
  * Nobobuhiro Iwamatsu <iwamatsu@nigauri.org>
  *
  */
 
 #include <common.h>
+#include <div64.h>
 #include <asm/processor.h>
+#include <asm/clk.h>
 #include <asm/io.h>
 
 #define TMU_MAX_COUNTER (~0UL)
-static int clk_adj = 1;
+
+static ulong timer_freq;
+
+static inline unsigned long long tick_to_time(unsigned long long tick)
+{
+       tick *= CONFIG_SYS_HZ;
+       do_div(tick, timer_freq);
+
+       return tick;
+}
+
+static inline unsigned long long usec_to_tick(unsigned long long usec)
+{
+       usec *= timer_freq;
+       do_div(usec, 1000000);
+
+       return usec;
+}
 
 static void tmu_timer_start (unsigned int timer)
 {
@@ -47,33 +69,30 @@ static void tmu_timer_stop (unsigned int timer)
 
 int timer_init (void)
 {
-       /* Divide clock by TMU_CLK_DIVIDER */
+       /* Divide clock by CONFIG_SYS_TMU_CLK_DIV */
        u16 bit = 0;
-       switch( TMU_CLK_DIVIDER ){
-       case 4:
-               bit = 0;
-               break;
-       case 16:
-               bit = 1;
-               break;
-       case 64: bit = 2;
+
+       switch (CONFIG_SYS_TMU_CLK_DIV) {
+       case 1024:
+               bit = 4;
                break;
        case 256:
                bit = 3;
                break;
-       case 1024:
-               bit = 4;
+       case 64:
+               bit = 2;
                break;
+       case 16:
+               bit = 1;
+               break;
+       case 4:
        default:
-               bit = 0;
                break;
        }
        writew(readw(TCR0) | bit, TCR0);
 
-       /* Clock adjustment calc */
-       clk_adj = (int)(1.0/((1.0/CONFIG_SYS_HZ)*1000000));
-       if (clk_adj < 1)
-               clk_adj = 1;
+       /* Calc clock rate */
+       timer_freq = get_tmu0_clk_rate() >> ((bit + 1) * 2);
 
        tmu_timer_stop(0);
        tmu_timer_start(0);
@@ -86,24 +105,22 @@ unsigned long long get_ticks (void)
        return 0 - readl(TCNT0);
 }
 
-static unsigned long get_usec (void)
+void __udelay (unsigned long usec)
 {
-       return (0 - readl(TCNT0));
-}
+       unsigned long long tmp;
+       ulong tmo;
 
-void udelay (unsigned long usec)
-{
-       unsigned int start = get_usec();
-       unsigned int end = start + (usec * clk_adj);
+       tmo = usec_to_tick(usec);
+       tmp = get_ticks() + tmo;        /* get current timestamp */
 
-       while (get_usec() < end)
-               continue;
+       while (get_ticks() < tmp)       /* loop till event */
+                /*NOP*/;
 }
 
 unsigned long get_timer (unsigned long base)
 {
-       /*  return msec */
-       return ((get_usec()/clk_adj)/1000) - base;
+       /* return msec */
+       return tick_to_time(get_ticks()) - base;
 }
 
 void set_timer (unsigned long t)
@@ -120,5 +137,5 @@ void reset_timer (void)
 
 unsigned long get_tbclk (void)
 {
-       return CONFIG_SYS_HZ;
+       return timer_freq;
 }