From 3b2e4f542e3ea5d116d5830f4eef9be97d872312 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 27 Aug 2024 19:44:25 -0600 Subject: x86: Ensure the CPU identity exists for timer init When bootstage is used the timer can be inited before the CPU identity is set up, resulting in the checks for the vendor not working. Add a special call to work around this. Signed-off-by: Simon Glass --- drivers/timer/tsc_timer.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 80c084f380d..d11227cf440 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -403,6 +403,10 @@ static void tsc_timer_ensure_setup(bool early) if (!gd->arch.clock_rate) { unsigned long fast_calibrate; + /* deal with this being called before x86_cpu_init_f() */ + if (!gd->arch.x86_vendor) + x86_get_identity_for_timer(); + /** * There is no obvious way to obtain this information from EFI * boot services. This value was measured on a Framework Laptop -- cgit v1.2.3 From 7c0f70b65b7c6ab0c09f87932615c65142542ed5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 27 Aug 2024 19:44:26 -0600 Subject: x86: Avoid timer-clock overflow When the clock speed is above about 4GHz, e.g. on modern PC hardware, the timer overflows, resulting in a much lower frequency than expected. Deal with this by capping the clock speed. It would be possible to move to a 64-bit value for the clock, but that is a pain to deal with. A better approach might be to express the clock in MHz but that is left for later consideration. Signed-off-by: Simon Glass --- drivers/timer/tsc_timer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index d11227cf440..2f2c2f27b7f 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -442,6 +442,7 @@ static void tsc_timer_ensure_setup(bool early) return; done: + fast_calibrate = min(fast_calibrate, 4000UL); if (!gd->arch.clock_rate) gd->arch.clock_rate = fast_calibrate * 1000000; } -- cgit v1.2.3 From ecf31113f17817f5ab9263937270255b6d05cdf9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Tue, 27 Aug 2024 19:44:27 -0600 Subject: x86: Sync up tsc_timer with Linux Since we are using the code from Linux, update it to the newer version in v6.11 Signed-off-by: Simon Glass --- drivers/timer/tsc_timer.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/timer/tsc_timer.c') diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index 2f2c2f27b7f..dd16ab320b2 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -83,7 +83,7 @@ static unsigned long cpu_mhz_from_cpuid(void) if (cpuid_eax(0) < 0x16) return 0; - return cpuid_eax(0x16); + return cpuid_eax(0x15); } /* @@ -299,10 +299,19 @@ static unsigned long __maybe_unused quick_pit_calibrate(void) if (!pit_expect_msb(0xff-i, &delta, &d2)) break; + delta -= tsc; + + /* + * Extrapolate the error and fail fast if the error will + * never be below 500 ppm. + */ + if (i == 1 && + d1 + d2 >= (delta * MAX_QUICK_PIT_ITERATIONS) >> 11) + return 0; + /* * Iterate until the error is less than 500 ppm */ - delta -= tsc; if (d1+d2 >= delta >> 11) continue; -- cgit v1.2.3