7 #include <minix/config.h>
8 #include <minix/const.h>
9 #include <minix/minlib.h>
10 #include <machine/archtypes.h>
14 #ifndef CONFIG_MAX_CPUS
15 #define CONFIG_MAX_CPUS 1
18 #define MICROHZ 1000000 /* number of micros per second */
19 #define MICROSPERTICK(h) (MICROHZ/(h)) /* number of micros per HZ tick */
24 if((r=tsc_calibrate()) != OK) \
25 panic("calibrate failed: %d", r); \
28 static u32_t calib_mhz
, Hz
= 0;
29 static int calibrated
= 0;
34 struct cpu_info cpu_info
[CONFIG_MAX_CPUS
];
39 /* Obtain CPU frequency from kernel */
40 if (sys_getcpuinfo(&cpu_info
)) {
41 printf("tsc_calibrate: cannot get cpu info\n");
45 /* For now, use the frequency of the first CPU; everything here will
46 * break down in case we get scheduled on multiple CPUs with different
47 * frequencies regardless
49 calib_mhz
= cpu_info
[0].freq
;
56 micro_delay(u32_t micros
)
65 /* We have to know when to end the delay. */
66 end
= add64(now
, mul64u(micros
, calib_mhz
));
68 /* If we have to wait for at least one HZ tick, use the regular
69 * tickdelay first. Round downwards on purpose, so the average
70 * half-tick we wait short (depending on where in the current tick
71 * we call tickdelay). We can correct for both overhead of tickdelay
72 * itself and the short wait in the busywait later.
74 if(micros
>= MICROSPERTICK(Hz
))
75 tickdelay(micros
*Hz
/MICROHZ
);
77 /* Wait (the rest) of the delay time using busywait. */
78 while(cmp64(now
, end
) < 0)
84 u32_t
tsc_64_to_micros(u64_t tsc
)
90 tmp
= div64u64(tsc
, calib_mhz
);
92 printf("tsc_64_to_micros: more than 2^32ms\n");
99 u32_t
tsc_to_micros(u32_t low
, u32_t high
)
101 return tsc_64_to_micros(make64(low
, high
));
104 u32_t
tsc_get_khz(void)
108 return calib_mhz
* 1000;