Skip to content

Commit d82f4a9

Browse files
najumon1980jhedberg
authored andcommitted
drivers: timer: tsc: retrieve clock frequency of system timer at runtime
add support for retrieve clock frequency (HW clock cycle per sec) of system timer at runtime by reading cpu clock via cpuid Signed-off-by: Najumon B.A <[email protected]>
1 parent 9631cd1 commit d82f4a9

File tree

1 file changed

+26
-1
lines changed

1 file changed

+26
-1
lines changed

drivers/timer/apic_tsc.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@
88
#include <zephyr/spinlock.h>
99
#include <zephyr/drivers/interrupt_controller/loapic.h>
1010
#include <zephyr/irq.h>
11+
#include <cpuid.h>
1112

1213
#define IA32_TSC_DEADLINE_MSR 0x6e0
1314
#define IA32_TSC_ADJUST_MSR 0x03b
1415

16+
#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME
17+
static uint64_t CYC_PER_TICK;
18+
extern int z_clock_hw_cycles_per_sec;
19+
#else
1520
#define CYC_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \
1621
/ (uint64_t) CONFIG_SYS_CLOCK_TICKS_PER_SEC)
22+
#endif
1723

1824
struct apic_timer_lvt {
1925
uint8_t vector : 8;
@@ -158,9 +164,11 @@ static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *
158164

159165
static int sys_clock_driver_init(void)
160166
{
161-
#ifdef CONFIG_ASSERT
167+
#if defined(CONFIG_ASSERT) || defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)
162168
uint32_t eax, ebx, ecx, edx;
169+
#endif
163170

171+
#ifdef CONFIG_ASSERT
164172
eax = 1; ecx = 0;
165173
cpuid(&eax, &ebx, &ecx, &edx);
166174
__ASSERT((ecx & BIT(24)) != 0, "No TSC Deadline support");
@@ -174,6 +182,23 @@ static int sys_clock_driver_init(void)
174182
__ASSERT((ebx & BIT(1)) != 0, "No TSC_ADJUST MSR support");
175183
#endif
176184

185+
#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME
186+
int tsc_freq;
187+
188+
eax = 0;
189+
ebx = 0;
190+
ecx = 0;
191+
if (!__get_cpuid(0x15, &eax, &ebx, &ecx, &edx)) {
192+
__ASSERT(false, "error cpuid leaf 0x15\n");
193+
}
194+
195+
__ASSERT((ebx != 0) && (ecx != 0), "No TSC/core crystal clock ratio is enumerated");
196+
197+
tsc_freq = (uint32_t)((ecx * (uint64_t)ebx) / eax);
198+
z_clock_hw_cycles_per_sec = tsc_freq;
199+
CYC_PER_TICK = tsc_freq/CONFIG_SYS_CLOCK_TICKS_PER_SEC;
200+
#endif
201+
177202
clear_tsc_adjust();
178203

179204
/* Timer interrupt number is runtime-fetched, so can't use

0 commit comments

Comments
 (0)