diff options
-rw-r--r-- | arch/x86/kernel/quirks.c | 69 |
1 files changed, 68 insertions, 1 deletions
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index 1fbc5380e27c..fbe32e7c3f5f 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
@@ -59,7 +59,8 @@ unsigned long force_hpet_address; | |||
59 | static enum { | 59 | static enum { |
60 | NONE_FORCE_HPET_RESUME, | 60 | NONE_FORCE_HPET_RESUME, |
61 | OLD_ICH_FORCE_HPET_RESUME, | 61 | OLD_ICH_FORCE_HPET_RESUME, |
62 | ICH_FORCE_HPET_RESUME | 62 | ICH_FORCE_HPET_RESUME, |
63 | VT8237_FORCE_HPET_RESUME | ||
63 | } force_hpet_resume_type; | 64 | } force_hpet_resume_type; |
64 | 65 | ||
65 | static void __iomem *rcba_base; | 66 | static void __iomem *rcba_base; |
@@ -240,6 +241,69 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, | |||
240 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12, | 241 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12, |
241 | old_ich_force_enable_hpet); | 242 | old_ich_force_enable_hpet); |
242 | 243 | ||
244 | |||
245 | static void vt8237_force_hpet_resume(void) | ||
246 | { | ||
247 | u32 val; | ||
248 | |||
249 | if (!force_hpet_address || !cached_dev) | ||
250 | return; | ||
251 | |||
252 | val = 0xfed00000 | 0x80; | ||
253 | pci_write_config_dword(cached_dev, 0x68, val); | ||
254 | |||
255 | pci_read_config_dword(cached_dev, 0x68, &val); | ||
256 | if (val & 0x80) | ||
257 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); | ||
258 | else | ||
259 | BUG(); | ||
260 | } | ||
261 | |||
262 | static void vt8237_force_enable_hpet(struct pci_dev *dev) | ||
263 | { | ||
264 | u32 uninitialized_var(val); | ||
265 | |||
266 | if (!hpet_force_user || hpet_address || force_hpet_address) | ||
267 | return; | ||
268 | |||
269 | pci_read_config_dword(dev, 0x68, &val); | ||
270 | /* | ||
271 | * Bit 7 is HPET enable bit. | ||
272 | * Bit 31:10 is HPET base address (contrary to what datasheet claims) | ||
273 | */ | ||
274 | if (val & 0x80) { | ||
275 | force_hpet_address = (val & ~0x3ff); | ||
276 | printk(KERN_DEBUG "HPET at base address 0x%lx\n", | ||
277 | force_hpet_address); | ||
278 | return; | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * HPET is disabled. Trying enabling at FED00000 and check | ||
283 | * whether it sticks | ||
284 | */ | ||
285 | val = 0xfed00000 | 0x80; | ||
286 | pci_write_config_dword(dev, 0x68, val); | ||
287 | |||
288 | pci_read_config_dword(dev, 0x68, &val); | ||
289 | if (val & 0x80) { | ||
290 | force_hpet_address = (val & ~0x3ff); | ||
291 | printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", | ||
292 | force_hpet_address); | ||
293 | cached_dev = dev; | ||
294 | force_hpet_resume_type = VT8237_FORCE_HPET_RESUME; | ||
295 | return; | ||
296 | } | ||
297 | |||
298 | printk(KERN_DEBUG "Failed to force enable HPET\n"); | ||
299 | } | ||
300 | |||
301 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, | ||
302 | vt8237_force_enable_hpet); | ||
303 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237, | ||
304 | vt8237_force_enable_hpet); | ||
305 | |||
306 | |||
243 | void force_hpet_resume(void) | 307 | void force_hpet_resume(void) |
244 | { | 308 | { |
245 | switch (force_hpet_resume_type) { | 309 | switch (force_hpet_resume_type) { |
@@ -249,6 +313,9 @@ void force_hpet_resume(void) | |||
249 | case OLD_ICH_FORCE_HPET_RESUME: | 313 | case OLD_ICH_FORCE_HPET_RESUME: |
250 | return old_ich_force_hpet_resume(); | 314 | return old_ich_force_hpet_resume(); |
251 | 315 | ||
316 | case VT8237_FORCE_HPET_RESUME: | ||
317 | return vt8237_force_hpet_resume(); | ||
318 | |||
252 | default: | 319 | default: |
253 | break; | 320 | break; |
254 | } | 321 | } |