1
2
3
4
5
6
7
8
9
10#include <common.h>
11#include <dm.h>
12#include <malloc.h>
13#include <timer.h>
14#include <asm/cpu.h>
15#include <asm/io.h>
16#include <asm/i8254.h>
17#include <asm/ibmpc.h>
18#include <asm/msr.h>
19#include <asm/u-boot-x86.h>
20
21#define MAX_NUM_FREQS 8
22
23DECLARE_GLOBAL_DATA_PTR;
24
25
26
27
28
29
30
31
32
33struct freq_desc {
34 u8 x86_family;
35 u8 x86_model;
36
37 u8 msr_plat;
38 u32 freqs[MAX_NUM_FREQS];
39};
40
41static struct freq_desc freq_desc_tables[] = {
42
43 { 6, 0x27, 0, { 0, 0, 0, 0, 0, 99840, 0, 83200 } },
44
45 { 6, 0x35, 0, { 0, 133200, 0, 0, 0, 99840, 0, 83200 } },
46
47 { 6, 0x4a, 1, { 0, 100000, 133300, 0, 0, 0, 0, 0 } },
48
49 { 6, 0x37, 1, { 83300, 100000, 133300, 116700, 80000, 0, 0, 0 } },
50
51 { 6, 0x5a, 1, { 83300, 100000, 133300, 100000, 0, 0, 0, 0 } },
52
53 { 6, 0x3a, 2, { 0, 0, 0, 0, 0, 0, 0, 0 } },
54};
55
56static int match_cpu(u8 family, u8 model)
57{
58 int i;
59
60 for (i = 0; i < ARRAY_SIZE(freq_desc_tables); i++) {
61 if ((family == freq_desc_tables[i].x86_family) &&
62 (model == freq_desc_tables[i].x86_model))
63 return i;
64 }
65
66 return -1;
67}
68
69
70#define id_to_freq(cpu_index, freq_id) \
71 (freq_desc_tables[cpu_index].freqs[freq_id])
72
73
74
75
76
77
78
79
80
81
82
83static unsigned long __maybe_unused cpu_mhz_from_msr(void)
84{
85 u32 lo, hi, ratio, freq_id, freq;
86 unsigned long res;
87 int cpu_index;
88
89 if (gd->arch.x86_vendor != X86_VENDOR_INTEL)
90 return 0;
91
92 cpu_index = match_cpu(gd->arch.x86, gd->arch.x86_model);
93 if (cpu_index < 0)
94 return 0;
95
96 if (freq_desc_tables[cpu_index].msr_plat) {
97 rdmsr(MSR_PLATFORM_INFO, lo, hi);
98 ratio = (lo >> 8) & 0xff;
99 } else {
100 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
101 ratio = (hi >> 8) & 0x1f;
102 }
103 debug("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio);
104
105 if (freq_desc_tables[cpu_index].msr_plat == 2) {
106
107 freq = 100000;
108 debug("Using frequency: %u KHz\n", freq);
109 } else {
110
111 rdmsr(MSR_FSB_FREQ, lo, hi);
112 freq_id = lo & 0x7;
113 freq = id_to_freq(cpu_index, freq_id);
114 debug("Resolved frequency ID: %u, frequency: %u KHz\n",
115 freq_id, freq);
116 }
117
118
119 res = freq * ratio / 1000;
120 debug("TSC runs at %lu MHz\n", res);
121
122 return res;
123}
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160static inline int pit_verify_msb(unsigned char val)
161{
162
163 inb(0x42);
164 return inb(0x42) == val;
165}
166
167static inline int pit_expect_msb(unsigned char val, u64 *tscp,
168 unsigned long *deltap)
169{
170 int count;
171 u64 tsc = 0, prev_tsc = 0;
172
173 for (count = 0; count < 50000; count++) {
174 if (!pit_verify_msb(val))
175 break;
176 prev_tsc = tsc;
177 tsc = rdtsc();
178 }
179 *deltap = rdtsc() - prev_tsc;
180 *tscp = tsc;
181
182
183
184
185
186 return count > 5;
187}
188
189
190
191
192
193
194
195#define MAX_QUICK_PIT_MS 50
196#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256)
197
198static unsigned long __maybe_unused quick_pit_calibrate(void)
199{
200 int i;
201 u64 tsc, delta;
202 unsigned long d1, d2;
203
204
205 outb((inb(0x61) & ~0x02) | 0x01, 0x61);
206
207
208
209
210
211
212
213
214
215
216 outb(0xb0, 0x43);
217
218
219 outb(0xff, 0x42);
220 outb(0xff, 0x42);
221
222
223
224
225
226
227
228 pit_verify_msb(0);
229
230 if (pit_expect_msb(0xff, &tsc, &d1)) {
231 for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) {
232 if (!pit_expect_msb(0xff-i, &delta, &d2))
233 break;
234
235
236
237
238 delta -= tsc;
239 if (d1+d2 >= delta >> 11)
240 continue;
241
242
243
244
245
246
247
248
249 if (!pit_verify_msb(0xfe - i))
250 break;
251 goto success;
252 }
253 }
254 debug("Fast TSC calibration failed\n");
255 return 0;
256
257success:
258
259
260
261
262
263
264
265
266
267
268
269
270
271 delta *= PIT_TICK_RATE;
272 delta /= (i*256*1000);
273 debug("Fast TSC calibration using PIT\n");
274 return delta / 1000;
275}
276
277
278unsigned notrace long get_tbclk_mhz(void)
279{
280 return get_tbclk() / 1000000;
281}
282
283static ulong get_ms_timer(void)
284{
285 return (get_ticks() * 1000) / get_tbclk();
286}
287
288ulong get_timer(ulong base)
289{
290 return get_ms_timer() - base;
291}
292
293ulong notrace timer_get_us(void)
294{
295 return get_ticks() / get_tbclk_mhz();
296}
297
298ulong timer_get_boot_us(void)
299{
300 return timer_get_us();
301}
302
303void __udelay(unsigned long usec)
304{
305 u64 now = get_ticks();
306 u64 stop;
307
308 stop = now + usec * get_tbclk_mhz();
309
310 while ((int64_t)(stop - get_ticks()) > 0)
311#if defined(CONFIG_QEMU) && defined(CONFIG_SMP)
312
313
314
315
316 asm volatile("pause");
317#else
318 ;
319#endif
320}
321
322static int tsc_timer_get_count(struct udevice *dev, u64 *count)
323{
324 u64 now_tick = rdtsc();
325
326 *count = now_tick - gd->arch.tsc_base;
327
328 return 0;
329}
330
331static int tsc_timer_probe(struct udevice *dev)
332{
333 struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev);
334
335 gd->arch.tsc_base = rdtsc();
336
337
338
339
340
341 if (!uc_priv->clock_rate) {
342 unsigned long fast_calibrate;
343
344 fast_calibrate = cpu_mhz_from_msr();
345 if (!fast_calibrate) {
346 fast_calibrate = quick_pit_calibrate();
347 if (!fast_calibrate)
348 panic("TSC frequency is ZERO");
349 }
350
351 uc_priv->clock_rate = fast_calibrate * 1000000;
352 }
353
354 return 0;
355}
356
357static const struct timer_ops tsc_timer_ops = {
358 .get_count = tsc_timer_get_count,
359};
360
361static const struct udevice_id tsc_timer_ids[] = {
362 { .compatible = "x86,tsc-timer", },
363 { }
364};
365
366U_BOOT_DRIVER(tsc_timer) = {
367 .name = "tsc_timer",
368 .id = UCLASS_TIMER,
369 .of_match = tsc_timer_ids,
370 .probe = tsc_timer_probe,
371 .ops = &tsc_timer_ops,
372 .flags = DM_FLAG_PRE_RELOC,
373};
374