Commit a6825f1c authored by Thomas Gleixner's avatar Thomas Gleixner

x86: hpet: workaround SB700 BIOS

AMD SB700 based systems with spread spectrum enabled use a SMM based
HPET emulation to provide proper frequency setting. The SMM code is
initialized with the first HPET register access and takes some time to
complete. During this time the config register reads 0xffffffff. We
check for max. 1000 loops whether the config register reads a non
0xffffffff value to make sure that HPET is up and running before we go
further. A counting loop is safe, as the HPET access takes thousands
of CPU cycles. On non SB700 based machines this check is only done
once and has no side effects.

Based on a quirk patch from: crane cai <crane.cai@amd.com>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent a58f03b0
...@@ -359,6 +359,7 @@ static int hpet_clocksource_register(void) ...@@ -359,6 +359,7 @@ static int hpet_clocksource_register(void)
int __init hpet_enable(void) int __init hpet_enable(void)
{ {
unsigned long id; unsigned long id;
int i;
if (!is_hpet_capable()) if (!is_hpet_capable())
return 0; return 0;
...@@ -369,6 +370,29 @@ int __init hpet_enable(void) ...@@ -369,6 +370,29 @@ int __init hpet_enable(void)
* Read the period and check for a sane value: * Read the period and check for a sane value:
*/ */
hpet_period = hpet_readl(HPET_PERIOD); hpet_period = hpet_readl(HPET_PERIOD);
/*
* AMD SB700 based systems with spread spectrum enabled use a
* SMM based HPET emulation to provide proper frequency
* setting. The SMM code is initialized with the first HPET
* register access and takes some time to complete. During
* this time the config register reads 0xffffffff. We check
* for max. 1000 loops whether the config register reads a non
* 0xffffffff value to make sure that HPET is up and running
* before we go further. A counting loop is safe, as the HPET
* access takes thousands of CPU cycles. On non SB700 based
* machines this check is only done once and has no side
* effects.
*/
for (i = 0; hpet_readl(HPET_CFG) == 0xFFFFFFFF; i++) {
if (i == 1000) {
printk(KERN_WARNING
"HPET config register value = 0xFFFFFFFF. "
"Disabling HPET\n");
goto out_nohpet;
}
}
if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD) if (hpet_period < HPET_MIN_PERIOD || hpet_period > HPET_MAX_PERIOD)
goto out_nohpet; goto out_nohpet;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment