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