]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - arch/arm/cpu/armv7/socfpga/timer.c
Add GPL-2.0+ SPDX-License-Identifier to source files
[karo-tx-uboot.git] / arch / arm / cpu / armv7 / socfpga / timer.c
1 /*
2  *  Copyright (C) 2012 Altera Corporation <www.altera.com>
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <asm/io.h>
9 #include <asm/arch/timer.h>
10
11 DECLARE_GLOBAL_DATA_PTR;
12
13 static const struct socfpga_timer *timer_base = (void *)CONFIG_SYS_TIMERBASE;
14
15 /*
16  * Timer initialization
17  */
18 int timer_init(void)
19 {
20         writel(TIMER_LOAD_VAL, &timer_base->load_val);
21         writel(TIMER_LOAD_VAL, &timer_base->curr_val);
22         writel(readl(&timer_base->ctrl) | 0x3, &timer_base->ctrl);
23         return 0;
24 }
25
26 static u32 read_timer(void)
27 {
28         return readl(&timer_base->curr_val);
29 }
30
31 /*
32  * Delay x useconds
33  */
34 void __udelay(unsigned long usec)
35 {
36         unsigned long now, last;
37         /*
38          * get the tmo value based on timer clock speed
39          * tmo = delay required / period of timer clock
40          */
41         long tmo = usec * CONFIG_TIMER_CLOCK_KHZ / 1000;
42
43         last = read_timer();
44         while (tmo > 0) {
45                 now = read_timer();
46                 if (last >= now)
47                         /* normal mode (non roll) */
48                         tmo -= last - now;
49                 else
50                         /* we have overflow of the count down timer */
51                         tmo -= TIMER_LOAD_VAL - last + now;
52                 last = now;
53         }
54 }
55
56 /*
57  * Get the timer value
58  */
59 ulong get_timer(ulong base)
60 {
61         return get_timer_masked() - base;
62 }
63
64 /*
65  * Timer : get the time difference
66  * Unit of tick is based on the CONFIG_SYS_HZ
67  */
68 ulong get_timer_masked(void)
69 {
70         /* current tick value */
71         ulong now = read_timer() / (CONFIG_TIMER_CLOCK_KHZ/CONFIG_SYS_HZ);
72         if (gd->arch.lastinc >= now) {
73                 /* normal mode (non roll) */
74                 /* move stamp forward with absolute diff ticks */
75                 gd->arch.tbl += gd->arch.lastinc - now;
76         } else {
77                 /* we have overflow of the count down timer */
78                 gd->arch.tbl += TIMER_LOAD_VAL - gd->arch.lastinc + now;
79         }
80         gd->arch.lastinc = now;
81         return gd->arch.tbl;
82 }
83
84 /*
85  * Reset the timer
86  */
87 void reset_timer(void)
88 {
89         /* capture current decrementer value time */
90         gd->arch.lastinc = read_timer() /
91                                 (CONFIG_TIMER_CLOCK_KHZ / CONFIG_SYS_HZ);
92         /* start "advancing" time stamp from 0 */
93         gd->arch.tbl = 0;
94 }