]>
Commit | Line | Data |
---|---|---|
e66c49fa | 1 | /* |
3bc599c9 PC |
2 | * Copyright (C) 2016, STMicroelectronics - All Rights Reserved |
3 | * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics. | |
e66c49fa VM |
4 | * |
5 | * SPDX-License-Identifier: GPL-2.0+ | |
6 | */ | |
7 | ||
8 | #include <common.h> | |
014a953c | 9 | #include <stm32_rcc.h> |
e66c49fa VM |
10 | #include <asm/io.h> |
11 | #include <asm/arch/stm32.h> | |
081de09d | 12 | #include <asm/arch/stm32_defs.h> |
e66c49fa | 13 | #include <asm/arch/gpt.h> |
e66c49fa VM |
14 | |
15 | #define READ_TIMER() (readl(&gpt1_regs_ptr->cnt) & GPT_FREE_RUNNING) | |
16 | #define GPT_RESOLUTION (CONFIG_SYS_HZ_CLOCK/CONFIG_STM32_HZ) | |
17 | ||
18 | DECLARE_GLOBAL_DATA_PTR; | |
19 | ||
20 | #define timestamp gd->arch.tbl | |
21 | #define lastdec gd->arch.lastinc | |
22 | ||
23 | int timer_init(void) | |
24 | { | |
25 | /* Timer2 clock configuration */ | |
081de09d | 26 | clock_setup(TIMER2_CLOCK_CFG); |
e66c49fa VM |
27 | /* Stop the timer */ |
28 | writel(readl(&gpt1_regs_ptr->cr1) & ~GPT_CR1_CEN, &gpt1_regs_ptr->cr1); | |
29 | ||
72dee54b | 30 | writel((CONFIG_SYS_CLK_FREQ / 2 / CONFIG_SYS_HZ_CLOCK) - 1, |
e66c49fa VM |
31 | &gpt1_regs_ptr->psc); |
32 | ||
33 | /* Configure timer for auto-reload */ | |
34 | writel(readl(&gpt1_regs_ptr->cr1) | GPT_MODE_AUTO_RELOAD, | |
35 | &gpt1_regs_ptr->cr1); | |
36 | ||
37 | /* load value for free running */ | |
38 | writel(GPT_FREE_RUNNING, &gpt1_regs_ptr->arr); | |
39 | ||
40 | /* start timer */ | |
41 | writel(readl(&gpt1_regs_ptr->cr1) | GPT_CR1_CEN, &gpt1_regs_ptr->cr1); | |
42 | ||
43 | writel(readl(&gpt1_regs_ptr->egr) | TIM_EGR_UG, &gpt1_regs_ptr->egr); | |
44 | ||
45 | /* Reset the timer */ | |
46 | lastdec = READ_TIMER(); | |
47 | timestamp = 0; | |
48 | ||
49 | return 0; | |
50 | } | |
51 | ||
52 | /* | |
53 | * timer without interrupts | |
54 | */ | |
55 | ulong get_timer(ulong base) | |
56 | { | |
57 | return (get_timer_masked() / GPT_RESOLUTION) - base; | |
58 | } | |
59 | ||
60 | void __udelay(unsigned long usec) | |
61 | { | |
62 | ulong tmo; | |
63 | ulong start = get_timer_masked(); | |
64 | ulong tenudelcnt = CONFIG_SYS_HZ_CLOCK / (1000 * 100); | |
65 | ulong rndoff; | |
66 | ||
67 | rndoff = (usec % 10) ? 1 : 0; | |
68 | ||
69 | /* tenudelcnt timer tick gives 10 microsecconds delay */ | |
70 | tmo = ((usec / 10) + rndoff) * tenudelcnt; | |
71 | ||
72 | while ((ulong) (get_timer_masked() - start) < tmo) | |
73 | ; | |
74 | } | |
75 | ||
76 | ulong get_timer_masked(void) | |
77 | { | |
78 | ulong now = READ_TIMER(); | |
79 | ||
80 | if (now >= lastdec) { | |
81 | /* normal mode */ | |
82 | timestamp += now - lastdec; | |
83 | } else { | |
84 | /* we have an overflow ... */ | |
85 | timestamp += now + GPT_FREE_RUNNING - lastdec; | |
86 | } | |
87 | lastdec = now; | |
88 | ||
89 | return timestamp; | |
90 | } | |
91 | ||
92 | void udelay_masked(unsigned long usec) | |
93 | { | |
94 | return udelay(usec); | |
95 | } | |
96 | ||
97 | /* | |
98 | * This function is derived from PowerPC code (read timebase as long long). | |
99 | * On ARM it just returns the timer value. | |
100 | */ | |
101 | unsigned long long get_ticks(void) | |
102 | { | |
103 | return get_timer(0); | |
104 | } | |
105 | ||
106 | /* | |
107 | * This function is derived from PowerPC code (timebase clock frequency). | |
108 | * On ARM it returns the number of timer ticks per second. | |
109 | */ | |
110 | ulong get_tbclk(void) | |
111 | { | |
112 | return CONFIG_STM32_HZ; | |
113 | } |