Commit 9fb34b01f7757ed772b77dd90e463c6e7499fef8

Authored by Simon Glass
Committed by Tom Rini
1 parent 9cb5eaf2cf

bootstage: Provide a default timer function

If CONFIG_SYS_TIMER_COUNTER is used we can provide a default microsecond
timer implementation.

Signed-off-by: Simon Glass <sjg@chromium.org>

Showing 1 changed file with 17 additions and 0 deletions Inline Diff

1 /* 1 /*
2 * (C) Copyright 2000-2009 2 * (C) Copyright 2000-2009
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. 3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 * 4 *
5 * SPDX-License-Identifier: GPL-2.0+ 5 * SPDX-License-Identifier: GPL-2.0+
6 */ 6 */
7 7
8 #include <common.h> 8 #include <common.h>
9 #include <dm.h> 9 #include <dm.h>
10 #include <errno.h> 10 #include <errno.h>
11 #include <timer.h> 11 #include <timer.h>
12 #include <watchdog.h> 12 #include <watchdog.h>
13 #include <div64.h> 13 #include <div64.h>
14 #include <asm/io.h> 14 #include <asm/io.h>
15 15
16 #ifndef CONFIG_WD_PERIOD 16 #ifndef CONFIG_WD_PERIOD
17 # define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */ 17 # define CONFIG_WD_PERIOD (10 * 1000 * 1000) /* 10 seconds default */
18 #endif 18 #endif
19 19
20 DECLARE_GLOBAL_DATA_PTR; 20 DECLARE_GLOBAL_DATA_PTR;
21 21
22 #ifdef CONFIG_SYS_TIMER_RATE 22 #ifdef CONFIG_SYS_TIMER_RATE
23 /* Returns tick rate in ticks per second */ 23 /* Returns tick rate in ticks per second */
24 ulong notrace get_tbclk(void) 24 ulong notrace get_tbclk(void)
25 { 25 {
26 return CONFIG_SYS_TIMER_RATE; 26 return CONFIG_SYS_TIMER_RATE;
27 } 27 }
28 #endif 28 #endif
29 29
30 #ifdef CONFIG_SYS_TIMER_COUNTER 30 #ifdef CONFIG_SYS_TIMER_COUNTER
31 unsigned long notrace timer_read_counter(void) 31 unsigned long notrace timer_read_counter(void)
32 { 32 {
33 #ifdef CONFIG_SYS_TIMER_COUNTS_DOWN 33 #ifdef CONFIG_SYS_TIMER_COUNTS_DOWN
34 return ~readl(CONFIG_SYS_TIMER_COUNTER); 34 return ~readl(CONFIG_SYS_TIMER_COUNTER);
35 #else 35 #else
36 return readl(CONFIG_SYS_TIMER_COUNTER); 36 return readl(CONFIG_SYS_TIMER_COUNTER);
37 #endif 37 #endif
38 } 38 }
39
40 ulong timer_get_boot_us(void)
41 {
42 ulong count = timer_read_counter();
43
44 #if CONFIG_SYS_TIMER_RATE == 1000000
45 return count;
46 #elif CONFIG_SYS_TIMER_RATE > 1000000
47 return lldiv(count, CONFIG_SYS_TIMER_RATE / 1000000);
48 #elif defined(CONFIG_SYS_TIMER_RATE)
49 return (unsigned long long)count * 1000000 / CONFIG_SYS_TIMER_RATE;
50 #else
51 /* Assume the counter is in microseconds */
52 return count;
53 #endif
54 }
55
39 #else 56 #else
40 extern unsigned long __weak timer_read_counter(void); 57 extern unsigned long __weak timer_read_counter(void);
41 #endif 58 #endif
42 59
43 #ifdef CONFIG_TIMER 60 #ifdef CONFIG_TIMER
44 ulong notrace get_tbclk(void) 61 ulong notrace get_tbclk(void)
45 { 62 {
46 if (!gd->timer) { 63 if (!gd->timer) {
47 #ifdef CONFIG_TIMER_EARLY 64 #ifdef CONFIG_TIMER_EARLY
48 return timer_early_get_rate(); 65 return timer_early_get_rate();
49 #else 66 #else
50 int ret; 67 int ret;
51 68
52 ret = dm_timer_init(); 69 ret = dm_timer_init();
53 if (ret) 70 if (ret)
54 return ret; 71 return ret;
55 #endif 72 #endif
56 } 73 }
57 74
58 return timer_get_rate(gd->timer); 75 return timer_get_rate(gd->timer);
59 } 76 }
60 77
61 uint64_t notrace get_ticks(void) 78 uint64_t notrace get_ticks(void)
62 { 79 {
63 u64 count; 80 u64 count;
64 int ret; 81 int ret;
65 82
66 if (!gd->timer) { 83 if (!gd->timer) {
67 #ifdef CONFIG_TIMER_EARLY 84 #ifdef CONFIG_TIMER_EARLY
68 return timer_early_get_count(); 85 return timer_early_get_count();
69 #else 86 #else
70 int ret; 87 int ret;
71 88
72 ret = dm_timer_init(); 89 ret = dm_timer_init();
73 if (ret) 90 if (ret)
74 return ret; 91 return ret;
75 #endif 92 #endif
76 } 93 }
77 94
78 ret = timer_get_count(gd->timer, &count); 95 ret = timer_get_count(gd->timer, &count);
79 if (ret) 96 if (ret)
80 return ret; 97 return ret;
81 98
82 return count; 99 return count;
83 } 100 }
84 101
85 #else /* !CONFIG_TIMER */ 102 #else /* !CONFIG_TIMER */
86 103
87 uint64_t __weak notrace get_ticks(void) 104 uint64_t __weak notrace get_ticks(void)
88 { 105 {
89 unsigned long now = timer_read_counter(); 106 unsigned long now = timer_read_counter();
90 107
91 /* increment tbu if tbl has rolled over */ 108 /* increment tbu if tbl has rolled over */
92 if (now < gd->timebase_l) 109 if (now < gd->timebase_l)
93 gd->timebase_h++; 110 gd->timebase_h++;
94 gd->timebase_l = now; 111 gd->timebase_l = now;
95 return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l; 112 return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l;
96 } 113 }
97 114
98 #endif /* CONFIG_TIMER */ 115 #endif /* CONFIG_TIMER */
99 116
100 /* Returns time in milliseconds */ 117 /* Returns time in milliseconds */
101 static uint64_t notrace tick_to_time(uint64_t tick) 118 static uint64_t notrace tick_to_time(uint64_t tick)
102 { 119 {
103 ulong div = get_tbclk(); 120 ulong div = get_tbclk();
104 121
105 tick *= CONFIG_SYS_HZ; 122 tick *= CONFIG_SYS_HZ;
106 do_div(tick, div); 123 do_div(tick, div);
107 return tick; 124 return tick;
108 } 125 }
109 126
110 int __weak timer_init(void) 127 int __weak timer_init(void)
111 { 128 {
112 return 0; 129 return 0;
113 } 130 }
114 131
115 /* Returns time in milliseconds */ 132 /* Returns time in milliseconds */
116 ulong __weak get_timer(ulong base) 133 ulong __weak get_timer(ulong base)
117 { 134 {
118 return tick_to_time(get_ticks()) - base; 135 return tick_to_time(get_ticks()) - base;
119 } 136 }
120 137
121 unsigned long __weak notrace timer_get_us(void) 138 unsigned long __weak notrace timer_get_us(void)
122 { 139 {
123 return tick_to_time(get_ticks() * 1000); 140 return tick_to_time(get_ticks() * 1000);
124 } 141 }
125 142
126 static uint64_t usec_to_tick(unsigned long usec) 143 static uint64_t usec_to_tick(unsigned long usec)
127 { 144 {
128 uint64_t tick = usec; 145 uint64_t tick = usec;
129 tick *= get_tbclk(); 146 tick *= get_tbclk();
130 do_div(tick, 1000000); 147 do_div(tick, 1000000);
131 return tick; 148 return tick;
132 } 149 }
133 150
134 void __weak __udelay(unsigned long usec) 151 void __weak __udelay(unsigned long usec)
135 { 152 {
136 uint64_t tmp; 153 uint64_t tmp;
137 154
138 tmp = get_ticks() + usec_to_tick(usec); /* get current timestamp */ 155 tmp = get_ticks() + usec_to_tick(usec); /* get current timestamp */
139 156
140 while (get_ticks() < tmp+1) /* loop till event */ 157 while (get_ticks() < tmp+1) /* loop till event */
141 /*NOP*/; 158 /*NOP*/;
142 } 159 }
143 160
144 /* ------------------------------------------------------------------------- */ 161 /* ------------------------------------------------------------------------- */
145 162
146 void udelay(unsigned long usec) 163 void udelay(unsigned long usec)
147 { 164 {
148 ulong kv; 165 ulong kv;
149 166
150 do { 167 do {
151 WATCHDOG_RESET(); 168 WATCHDOG_RESET();
152 kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec; 169 kv = usec > CONFIG_WD_PERIOD ? CONFIG_WD_PERIOD : usec;
153 __udelay (kv); 170 __udelay (kv);
154 usec -= kv; 171 usec -= kv;
155 } while(usec); 172 } while(usec);
156 } 173 }
157 174