]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | // SPDX-License-Identifier: GPL-2.0+ |
64fdf452 SB |
2 | /* |
3 | * (C) Copyright 2007 | |
4 | * Sascha Hauer, Pengutronix | |
5 | * | |
6 | * (C) Copyright 2009 Freescale Semiconductor, Inc. | |
64fdf452 SB |
7 | */ |
8 | ||
9 | #include <common.h> | |
691d719d | 10 | #include <init.h> |
6887c5be | 11 | #include <time.h> |
64fdf452 | 12 | #include <asm/io.h> |
782bb0d2 | 13 | #include <div64.h> |
401d1c4f | 14 | #include <asm/global_data.h> |
64fdf452 | 15 | #include <asm/arch/imx-regs.h> |
833b6435 | 16 | #include <asm/arch/clock.h> |
1a1f7950 | 17 | #include <asm/arch/sys_proto.h> |
64fdf452 SB |
18 | |
19 | /* General purpose timers registers */ | |
20 | struct mxc_gpt { | |
21 | unsigned int control; | |
22 | unsigned int prescaler; | |
23 | unsigned int status; | |
24 | unsigned int nouse[6]; | |
25 | unsigned int counter; | |
26 | }; | |
27 | ||
28 | static struct mxc_gpt *cur_gpt = (struct mxc_gpt *)GPT1_BASE_ADDR; | |
29 | ||
30 | /* General purpose timers bitfields */ | |
18936ee2 | 31 | #define GPTCR_SWR (1 << 15) /* Software reset */ |
1a1f7950 | 32 | #define GPTCR_24MEN (1 << 10) /* Enable 24MHz clock input */ |
18936ee2 | 33 | #define GPTCR_FRR (1 << 9) /* Freerun / restart */ |
1a1f7950 YL |
34 | #define GPTCR_CLKSOURCE_32 (4 << 6) /* Clock source 32khz */ |
35 | #define GPTCR_CLKSOURCE_OSC (5 << 6) /* Clock source OSC */ | |
36 | #define GPTCR_CLKSOURCE_PRE (1 << 6) /* Clock source PRECLK */ | |
37 | #define GPTCR_CLKSOURCE_MASK (0x7 << 6) | |
18936ee2 | 38 | #define GPTCR_TEN 1 /* Timer enable */ |
64fdf452 | 39 | |
1a1f7950 YL |
40 | #define GPTPR_PRESCALER24M_SHIFT 12 |
41 | #define GPTPR_PRESCALER24M_MASK (0xF << GPTPR_PRESCALER24M_SHIFT) | |
42 | ||
8cd20179 YL |
43 | DECLARE_GLOBAL_DATA_PTR; |
44 | ||
1a1f7950 YL |
45 | static inline int gpt_has_clk_source_osc(void) |
46 | { | |
27cd0da4 | 47 | if (((is_mx6dq()) && (soc_rev() > CHIP_REV_1_0)) || |
988acd2d | 48 | is_mx6dqp() || is_mx6sdl() || is_mx6sx() || is_mx6ul() || |
8cd20179 | 49 | is_mx6ull() || is_mx6sll() || is_mx7()) |
1a1f7950 YL |
50 | return 1; |
51 | ||
52 | return 0; | |
1a1f7950 YL |
53 | } |
54 | ||
55 | static inline ulong gpt_get_clk(void) | |
56 | { | |
57 | #ifdef CONFIG_MXC_GPT_HCLK | |
58 | if (gpt_has_clk_source_osc()) | |
59 | return MXC_HCLK >> 3; | |
60 | else | |
61 | return mxc_get_clock(MXC_IPG_PERCLK); | |
62 | #else | |
63 | return MXC_CLK32; | |
64 | #endif | |
65 | } | |
782bb0d2 | 66 | |
64fdf452 SB |
67 | int timer_init(void) |
68 | { | |
69 | int i; | |
70 | ||
71 | /* setup GP Timer 1 */ | |
72 | __raw_writel(GPTCR_SWR, &cur_gpt->control); | |
73 | ||
74 | /* We have no udelay by now */ | |
8cd20179 YL |
75 | for (i = 0; i < 100; i++) |
76 | __raw_writel(0, &cur_gpt->control); | |
64fdf452 | 77 | |
64fdf452 | 78 | i = __raw_readl(&cur_gpt->control); |
1a1f7950 YL |
79 | i &= ~GPTCR_CLKSOURCE_MASK; |
80 | ||
81 | #ifdef CONFIG_MXC_GPT_HCLK | |
82 | if (gpt_has_clk_source_osc()) { | |
83 | i |= GPTCR_CLKSOURCE_OSC | GPTCR_TEN; | |
84 | ||
fddac805 PF |
85 | /* |
86 | * For DL/S, SX, UL, ULL, SLL set 24Mhz OSC | |
87 | * Enable bit and prescaler | |
88 | */ | |
89 | if (is_mx6sdl() || is_mx6sx() || is_mx6ul() || is_mx6ull() || | |
8cd20179 | 90 | is_mx6sll() || is_mx7()) { |
1a1f7950 YL |
91 | i |= GPTCR_24MEN; |
92 | ||
93 | /* Produce 3Mhz clock */ | |
94 | __raw_writel((7 << GPTPR_PRESCALER24M_SHIFT), | |
95 | &cur_gpt->prescaler); | |
96 | } | |
97 | } else { | |
98 | i |= GPTCR_CLKSOURCE_PRE | GPTCR_TEN; | |
99 | } | |
100 | #else | |
101 | __raw_writel(0, &cur_gpt->prescaler); /* 32Khz */ | |
102 | i |= GPTCR_CLKSOURCE_32 | GPTCR_TEN; | |
103 | #endif | |
104 | __raw_writel(i, &cur_gpt->control); | |
64fdf452 | 105 | |
8cd20179 YL |
106 | gd->arch.tbl = __raw_readl(&cur_gpt->counter); |
107 | gd->arch.tbu = 0; | |
108 | ||
17659d7d | 109 | return 0; |
64fdf452 SB |
110 | } |
111 | ||
2bb01482 | 112 | unsigned long timer_read_counter(void) |
64fdf452 | 113 | { |
2bb01482 | 114 | return __raw_readl(&cur_gpt->counter); /* current tick value */ |
782bb0d2 | 115 | } |
64fdf452 | 116 | |
782bb0d2 SB |
117 | /* |
118 | * This function is derived from PowerPC code (timebase clock frequency). | |
119 | * On ARM it returns the number of timer ticks per second. | |
120 | */ | |
121 | ulong get_tbclk(void) | |
122 | { | |
1a1f7950 | 123 | return gpt_get_clk(); |
64fdf452 | 124 | } |
436baaa2 PF |
125 | |
126 | /* | |
127 | * This function is intended for SHORT delays only. | |
128 | * It will overflow at around 10 seconds @ 400MHz, | |
129 | * or 20 seconds @ 200MHz. | |
130 | */ | |
131 | unsigned long usec2ticks(unsigned long _usec) | |
132 | { | |
133 | unsigned long long usec = _usec; | |
134 | ||
135 | usec *= get_tbclk(); | |
136 | usec += 999999; | |
137 | do_div(usec, 1000000); | |
138 | ||
139 | return usec; | |
140 | } |