Skip to content

Commit bad3db1

Browse files
Anson HuangShawn Guo
authored andcommitted
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 <[email protected]> Signed-off-by: Shawn Guo <[email protected]>
1 parent 6f11c69 commit bad3db1

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

arch/arm/mach-imx/time.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,22 @@
6060
#define MX2_TSTAT_CAPT (1 << 1)
6161
#define MX2_TSTAT_COMP (1 << 0)
6262

63-
/* MX31, MX35, MX25, MX5 */
63+
/* MX31, MX35, MX25, MX5, MX6 */
6464
#define V2_TCTL_WAITEN (1 << 3) /* Wait enable mode */
6565
#define V2_TCTL_CLK_IPG (1 << 6)
6666
#define V2_TCTL_CLK_PER (2 << 6)
67+
#define V2_TCTL_CLK_OSC_DIV8 (5 << 6)
6768
#define V2_TCTL_FRR (1 << 9)
69+
#define V2_TCTL_24MEN (1 << 10)
70+
#define V2_TPRER_PRE24M 12
6871
#define V2_IR 0x0c
6972
#define V2_TSTAT 0x08
7073
#define V2_TSTAT_OF1 (1 << 0)
7174
#define V2_TCN 0x24
7275
#define V2_TCMP 0x10
7376

77+
#define V2_TIMER_RATE_OSC_DIV8 3000000
78+
7479
#define timer_is_v1() (cpu_is_mx1() || cpu_is_mx21() || cpu_is_mx27())
7580
#define timer_is_v2() (!timer_is_v1())
7681

@@ -312,10 +317,22 @@ static void __init _mxc_timer_init(int irq,
312317
__raw_writel(0, timer_base + MXC_TCTL);
313318
__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
314319

315-
if (timer_is_v2())
316-
tctl_val = V2_TCTL_CLK_PER | V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
317-
else
320+
if (timer_is_v2()) {
321+
tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN;
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 {
318334
tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
335+
}
319336

320337
__raw_writel(tctl_val, timer_base + MXC_TCTL);
321338

@@ -349,9 +366,13 @@ static void __init mxc_timer_init_dt(struct device_node *np)
349366
WARN_ON(!timer_base);
350367
irq = irq_of_parse_and_map(np, 0);
351368

352-
clk_per = of_clk_get_by_name(np, "per");
353369
clk_ipg = of_clk_get_by_name(np, "ipg");
354370

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+
355376
_mxc_timer_init(irq, clk_per, clk_ipg);
356377
}
357378
CLOCKSOURCE_OF_DECLARE(mx1_timer, "fsl,imx1-gpt", mxc_timer_init_dt);

0 commit comments

Comments
 (0)