aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorAnson Huang <b20788@freescale.com>2014-09-10 23:29:42 -0400
committerShawn Guo <shawn.guo@freescale.com>2014-09-15 22:09:41 -0400
commitbad3db104f8922df2c84fd7653cfbcbc93cd0cb7 (patch)
tree19bea59e889eefaed55dea1de283508b45093af4 /arch
parent6f11c69d35d5b1db0ec4cfccd0188b00eada3ad3 (diff)
ARM: imx: source gpt per clk from OSC for system timer
On i.MX6Q TO > 1.0, i.MX6DL and i.MX6SX, gpt per clock can be from OSC instead of ipg_per, as ipg_per's rate may be scaled when system enter low bus mode, to keep system timer NOT drift, better to make gpt per clock at fixed rate, here add support for gpt per clock to be from OSC which is at fixed rate always. There are some difference on this implementation of gpt per clock source, see below for details: i.MX6Q TO > 1.0: GPT_CR_CLKSRC, b'101 selects fix clock of OSC / 8 for gpt per clk; i.MX6DL and i.MX6SX: GPT_CR_CLKSRC, b'101 selects OSC for gpt per clk, and we must enable GPT_CR_24MEM to enable OSC clk source for gpt per, GPT_PR_PRESCALER24M is for pre-scaling of this OSC clk, here set it to 8 to make gpt per clk is 3MHz; i.MX6SL: ipg_per can be from OSC directly, so no need to implement this new clk source for gpt per. Signed-off-by: Anson Huang <b20788@freescale.com> Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-imx/time.c31
1 files changed, 26 insertions, 5 deletions
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index bf92e5a351c0..15d18e198303 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -60,17 +60,22 @@
60#define MX2_TSTAT_CAPT (1 << 1) 60#define MX2_TSTAT_CAPT (1 << 1)
61#define MX2_TSTAT_COMP (1 << 0) 61#define MX2_TSTAT_COMP (1 << 0)
62 62
63/* MX31, MX35, MX25, MX5 */ 63/* MX31, MX35, MX25, MX5, MX6 */
64#define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */ 64#define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */
65#define V2_TCTL_CLK_IPG (1 << 6) 65#define V2_TCTL_CLK_IPG (1 << 6)
66#define V2_TCTL_CLK_PER (2 << 6) 66#define V2_TCTL_CLK_PER (2 << 6)
67#define V2_TCTL_CLK_OSC_DIV8 (5 << 6)
67#define V2_TCTL_FRR (1 << 9) 68#define V2_TCTL_FRR (1 << 9)
69#define V2_TCTL_24MEN (1 << 10)
70#define V2_TPRER_PRE24M 12
68#define V2_IR 0x0c 71#define V2_IR 0x0c
69#define V2_TSTAT 0x08 72#define V2_TSTAT 0x08
70#define V2_TSTAT_OF1 (1 << 0) 73#define V2_TSTAT_OF1 (1 << 0)
71#define V2_TCN 0x24 74#define V2_TCN 0x24
72#define V2_TCMP 0x10 75#define V2_TCMP 0x10
73 76
77#define V2_TIMER_RATE_OSC_DIV8 3000000
78
74#define timer_is_v1() (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27()) 79#define timer_is_v1() (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
75#define timer_is_v2() (!timer_is_v1()) 80#define timer_is_v2() (!timer_is_v1())
76 81
@@ -312,10 +317,22 @@ static void __init _mxc_timer_init(int irq,
312 __raw_writel(0, timer_base + MXC_TCTL); 317 __raw_writel(0, timer_base + MXC_TCTL);
313 __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */ 318 __raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
314 319
315 if (timer_is_v2()) 320 if (timer_is_v2()) {
316 tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; 321 tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
317 else 322 if (clk_get_rate(clk_per) == V2_TIMER_RATE_OSC_DIV8) {
323 tctl_val |= V2_TCTL_CLK_OSC_DIV8;
324 if (cpu_is_imx6dl() || cpu_is_imx6sx()) {
325 /* 24 / 8 = 3 MHz */
326 __raw_writel(7 << V2_TPRER_PRE24M,
327 timer_base + MXC_TPRER);
328 tctl_val |= V2_TCTL_24MEN;
329 }
330 } else {
331 tctl_val |= V2_TCTL_CLK_PER;
332 }
333 } else {
318 tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; 334 tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
335 }
319 336
320 __raw_writel(tctl_val, timer_base + MXC_TCTL); 337 __raw_writel(tctl_val, timer_base + MXC_TCTL);
321 338
@@ -349,9 +366,13 @@ static void __init mxc_timer_init_dt(struct device_node *np)
349 WARN_ON(!timer_base); 366 WARN_ON(!timer_base);
350 irq = irq_of_parse_and_map(np, 0); 367 irq = irq_of_parse_and_map(np, 0);
351 368
352 clk_per = of_clk_get_by_name(np, "per");
353 clk_ipg = of_clk_get_by_name(np, "ipg"); 369 clk_ipg = of_clk_get_by_name(np, "ipg");
354 370
371 /* Try osc_per first, and fall back to per otherwise */
372 clk_per = of_clk_get_by_name(np, "osc_per");
373 if (IS_ERR(clk_per))
374 clk_per = of_clk_get_by_name(np, "per");
375
355 _mxc_timer_init(irq, clk_per, clk_ipg); 376 _mxc_timer_init(irq, clk_per, clk_ipg);
356} 377}
357CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt); 378CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);