]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/arm/plat-s3c/time.c
Merge branch 'topic/usb-caiaq' into for-linus
[linux-2.6-omap-h63xx.git] / arch / arm / plat-s3c / time.c
index a581ff7ba664b835da5eeee73b330cd06cd23162..3b27b29da4787e452f76c2c2f5573e3605e06df6 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/platform_device.h>
 
 #include <asm/system.h>
 #include <asm/leds.h>
@@ -147,6 +148,10 @@ static struct irqaction s3c2410_timer_irq = {
        machine_is_anubis()     || \
        machine_is_osiris())
 
+static struct clk *tin;
+static struct clk *tdiv;
+static struct clk *timerclk;
+
 /*
  * Set up timer interrupt, and return the current time in seconds.
  *
@@ -162,12 +167,6 @@ static void s3c2410_timer_setup (void)
 
        tcnt = TICK_MAX;  /* default value for tcnt */
 
-       /* read the current timer configuration bits */
-
-       tcon = __raw_readl(S3C2410_TCON);
-       tcfg1 = __raw_readl(S3C2410_TCFG1);
-       tcfg0 = __raw_readl(S3C2410_TCFG0);
-
        /* configure the system for whichever machine is in use */
 
        if (use_tclk1_12()) {
@@ -175,11 +174,13 @@ static void s3c2410_timer_setup (void)
                timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
                tcnt = 12000000 / HZ;
 
+               tcfg1 = __raw_readl(S3C2410_TCFG1);
                tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
                tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
+               __raw_writel(tcfg1, S3C2410_TCFG1);
        } else {
                unsigned long pclk;
-               struct clk *clk;
+               struct clk *tscaler;
 
                /* for the h1940 (and others), we use the pclk from the core
                 * to generate the timer values. since values around 50 to
@@ -190,29 +191,25 @@ static void s3c2410_timer_setup (void)
                 * (8.45 ticks per usec)
                 */
 
-               /* this is used as default if no other timer can be found */
-
-               clk = clk_get(NULL, "timers");
-               if (IS_ERR(clk))
-                       panic("failed to get clock for system timer");
-
-               clk_enable(clk);
-
-               pclk = clk_get_rate(clk);
+               pclk = clk_get_rate(timerclk);
 
                /* configure clock tick */
 
                timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
 
-               tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
-               tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
+               tscaler = clk_get_parent(tdiv);
 
-               tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
-               tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
+               clk_set_rate(tscaler, pclk / 3);
+               clk_set_rate(tdiv, pclk / 6);
+               clk_set_parent(tin, tdiv);
 
-               tcnt = (pclk / 6) / HZ;
+               tcnt = clk_get_rate(tin) / HZ;
        }
 
+       tcon = __raw_readl(S3C2410_TCON);
+       tcfg0 = __raw_readl(S3C2410_TCFG0);
+       tcfg1 = __raw_readl(S3C2410_TCFG1);
+
        /* timers reload after counting zero, so reduce the count by 1 */
 
        tcnt--;
@@ -248,8 +245,35 @@ static void s3c2410_timer_setup (void)
        __raw_writel(tcon, S3C2410_TCON);
 }
 
+static void __init s3c2410_timer_resources(void)
+{
+       struct platform_device tmpdev;
+
+       tmpdev.dev.bus = &platform_bus_type;
+       tmpdev.id = 4;
+
+       timerclk = clk_get(NULL, "timers");
+       if (IS_ERR(timerclk))
+               panic("failed to get clock for system timer");
+
+       clk_enable(timerclk);
+
+       if (!use_tclk1_12()) {
+               tin = clk_get(&tmpdev.dev, "pwm-tin");
+               if (IS_ERR(tin))
+                       panic("failed to get pwm-tin clock for system timer");
+
+               tdiv = clk_get(&tmpdev.dev, "pwm-tdiv");
+               if (IS_ERR(tdiv))
+                       panic("failed to get pwm-tdiv clock for system timer");
+       }
+
+       clk_enable(tin);
+}
+
 static void __init s3c2410_timer_init(void)
 {
+       s3c2410_timer_resources();
        s3c2410_timer_setup();
        setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
 }