Commit 9fb34b01f7757ed772b77dd90e463c6e7499fef8
Committed by
Tom Rini
1 parent
9cb5eaf2cf
Exists in
smarc_8mq_lf_v2020.04
and in
17 other branches
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
lib/time.c
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 |