diff options
-rw-r--r-- | arch/x86/kernel/quirks.c | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c index d13858818100..f6a11b9b1f98 100644 --- a/arch/x86/kernel/quirks.c +++ b/arch/x86/kernel/quirks.c | |||
@@ -354,9 +354,27 @@ static void ati_force_hpet_resume(void) | |||
354 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); | 354 | printk(KERN_DEBUG "Force enabled HPET at resume\n"); |
355 | } | 355 | } |
356 | 356 | ||
357 | static u32 ati_ixp4x0_rev(struct pci_dev *dev) | ||
358 | { | ||
359 | u32 d; | ||
360 | u8 b; | ||
361 | |||
362 | pci_read_config_byte(dev, 0xac, &b); | ||
363 | b &= ~(1<<5); | ||
364 | pci_write_config_byte(dev, 0xac, b); | ||
365 | pci_read_config_dword(dev, 0x70, &d); | ||
366 | d |= 1<<8; | ||
367 | pci_write_config_dword(dev, 0x70, d); | ||
368 | pci_read_config_dword(dev, 0x8, &d); | ||
369 | d &= 0xff; | ||
370 | dev_printk(KERN_DEBUG, &dev->dev, "SB4X0 revision 0x%x\n", d); | ||
371 | return d; | ||
372 | } | ||
373 | |||
357 | static void ati_force_enable_hpet(struct pci_dev *dev) | 374 | static void ati_force_enable_hpet(struct pci_dev *dev) |
358 | { | 375 | { |
359 | u32 uninitialized_var(val); | 376 | u32 d, val; |
377 | u8 b; | ||
360 | 378 | ||
361 | if (hpet_address || force_hpet_address) | 379 | if (hpet_address || force_hpet_address) |
362 | return; | 380 | return; |
@@ -366,14 +384,33 @@ static void ati_force_enable_hpet(struct pci_dev *dev) | |||
366 | return; | 384 | return; |
367 | } | 385 | } |
368 | 386 | ||
387 | d = ati_ixp4x0_rev(dev); | ||
388 | if (d < 0x82) | ||
389 | return; | ||
390 | |||
391 | /* base address */ | ||
369 | pci_write_config_dword(dev, 0x14, 0xfed00000); | 392 | pci_write_config_dword(dev, 0x14, 0xfed00000); |
370 | pci_read_config_dword(dev, 0x14, &val); | 393 | pci_read_config_dword(dev, 0x14, &val); |
394 | |||
395 | /* enable interrupt */ | ||
396 | outb(0x72, 0xcd6); b = inb(0xcd7); | ||
397 | b |= 0x1; | ||
398 | outb(0x72, 0xcd6); outb(b, 0xcd7); | ||
399 | outb(0x72, 0xcd6); b = inb(0xcd7); | ||
400 | if (!(b & 0x1)) | ||
401 | return; | ||
402 | pci_read_config_dword(dev, 0x64, &d); | ||
403 | d |= (1<<10); | ||
404 | pci_write_config_dword(dev, 0x64, d); | ||
405 | pci_read_config_dword(dev, 0x64, &d); | ||
406 | if (!(d & (1<<10))) | ||
407 | return; | ||
408 | |||
371 | force_hpet_address = val; | 409 | force_hpet_address = val; |
372 | force_hpet_resume_type = ATI_FORCE_HPET_RESUME; | 410 | force_hpet_resume_type = ATI_FORCE_HPET_RESUME; |
373 | dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n", | 411 | dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n", |
374 | force_hpet_address); | 412 | force_hpet_address); |
375 | cached_dev = dev; | 413 | cached_dev = dev; |
376 | return; | ||
377 | } | 414 | } |
378 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, | 415 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, |
379 | ati_force_enable_hpet); | 416 | ati_force_enable_hpet); |