Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/sage/ceph...
[sfrench/cifs-2.6.git] / arch / arm / mach-imx / time.c
index bf92e5a351c05e384136f206b1651e56b9e6e46f..15d18e198303f16ae6a77bf476c46acd066a6886 100644 (file)
 #define MX2_TSTAT_CAPT         (1 << 1)
 #define MX2_TSTAT_COMP         (1 << 0)
 
-/* MX31, MX35, MX25, MX5 */
+/* MX31, MX35, MX25, MX5, MX6 */
 #define V2_TCTL_WAITEN         (1 << 3) /* Wait enable mode */
 #define V2_TCTL_CLK_IPG                (1 << 6)
 #define V2_TCTL_CLK_PER                (2 << 6)
+#define V2_TCTL_CLK_OSC_DIV8   (5 << 6)
 #define V2_TCTL_FRR            (1 << 9)
+#define V2_TCTL_24MEN          (1 << 10)
+#define V2_TPRER_PRE24M                12
 #define V2_IR                  0x0c
 #define V2_TSTAT               0x08
 #define V2_TSTAT_OF1           (1 << 0)
 #define V2_TCN                 0x24
 #define V2_TCMP                        0x10
 
+#define V2_TIMER_RATE_OSC_DIV8 3000000
+
 #define timer_is_v1()  (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
 #define timer_is_v2()  (!timer_is_v1())
 
@@ -312,10 +317,22 @@ static void __init _mxc_timer_init(int irq,
        __raw_writel(0, timer_base + MXC_TCTL);
        __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
 
-       if (timer_is_v2())
-               tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
-       else
+       if (timer_is_v2()) {
+               tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
+               if (clk_get_rate(clk_per) == V2_TIMER_RATE_OSC_DIV8) {
+                       tctl_val |= V2_TCTL_CLK_OSC_DIV8;
+                       if (cpu_is_imx6dl() || cpu_is_imx6sx()) {
+                               /* 24 / 8 = 3 MHz */
+                               __raw_writel(7 << V2_TPRER_PRE24M,
+                                       timer_base + MXC_TPRER);
+                               tctl_val |= V2_TCTL_24MEN;
+                       }
+               } else {
+                       tctl_val |= V2_TCTL_CLK_PER;
+               }
+       } else {
                tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
+       }
 
        __raw_writel(tctl_val, timer_base + MXC_TCTL);
 
@@ -349,9 +366,13 @@ static void __init mxc_timer_init_dt(struct device_node *np)
        WARN_ON(!timer_base);
        irq = irq_of_parse_and_map(np, 0);
 
-       clk_per = of_clk_get_by_name(np, "per");
        clk_ipg = of_clk_get_by_name(np, "ipg");
 
+       /* Try osc_per first, and fall back to per otherwise */
+       clk_per = of_clk_get_by_name(np, "osc_per");
+       if (IS_ERR(clk_per))
+               clk_per = of_clk_get_by_name(np, "per");
+
        _mxc_timer_init(irq, clk_per, clk_ipg);
 }
 CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);