1/* Various workarounds for chipset bugs. 2 This code runs very early and can't use the regular PCI subsystem 3 The entries are keyed to PCI bridges which usually identify chipsets 4 uniquely. 5 This is only for whole classes of chipsets with specific problems which 6 need early invasive action (e.g. before the timers are initialized). 7 Most PCI device specific workarounds can be done later and should be 8 in standard PCI quirks 9 Mainboard specific bugs should be handled by DMI entries. 10 CPU specific bugs in setup.c */ 11 12#include <linux/pci.h> 13#include <linux/acpi.h> 14#include <linux/pci_ids.h> 15#include <asm/pci-direct.h> 16#include <asm/proto.h> 17#include <asm/dma.h> 18 19static void __init via_bugs(void) 20{ 21#ifdef CONFIG_IOMMU 22 if ((end_pfn > MAX_DMA32_PFN || force_iommu) && 23 !iommu_aperture_allowed) { 24 printk(KERN_INFO 25 "Looks like a VIA chipset. Disabling IOMMU. Override with iommu=allowed\n"); 26 iommu_aperture_disabled = 1; 27 } 28#endif 29} 30 31#ifdef CONFIG_ACPI 32 33static int __init nvidia_hpet_check(struct acpi_table_header *header) 34{ 35 return 0; 36} 37#endif 38 39static void __init nvidia_bugs(void) 40{ 41#ifdef CONFIG_ACPI 42 /* 43 * All timer overrides on Nvidia are 44 * wrong unless HPET is enabled. 45 * Unfortunately that's not true on many Asus boards. 46 * We don't know yet how to detect this automatically, but 47 * at least allow a command line override. 48 */ 49 if (acpi_use_timer_override) 50 return; 51 52 if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) { 53 acpi_skip_timer_override = 1; 54 printk(KERN_INFO "Nvidia board " 55 "detected. Ignoring ACPI " 56 "timer override.\n"); 57 printk(KERN_INFO "If you got timer trouble " 58 "try acpi_use_timer_override\n"); 59 } 60#endif 61 /* RED-PEN skip them on mptables too? */ 62 63} 64 65static void __init ati_bugs(void) 66{ 67 if (timer_over_8254 == 1) { 68 timer_over_8254 = 0; 69 printk(KERN_INFO 70 "ATI board detected. Disabling timer routing over 8254.\n"); 71 } 72} 73 74struct chipset { 75 u16 vendor; 76 void (*f)(void); 77}; 78 79static struct chipset early_qrk[] __initdata = { 80 { PCI_VENDOR_ID_NVIDIA, nvidia_bugs }, 81 { PCI_VENDOR_ID_VIA, via_bugs }, 82 { PCI_VENDOR_ID_ATI, ati_bugs }, 83 {} 84}; 85 86void __init early_quirks(void) 87{ 88 int num, slot, func; 89 90 if (!early_pci_allowed()) 91 return; 92 93 /* Poor man's PCI discovery */ 94 for (num = 0; num < 32; num++) { 95 for (slot = 0; slot < 32; slot++) { 96 for (func = 0; func < 8; func++) { 97 u32 class; 98 u32 vendor; 99 u8 type; 100 int i; 101 class = read_pci_config(num,slot,func, 102 PCI_CLASS_REVISION); 103 if (class == 0xffffffff) 104 break; 105 106 if ((class >> 16) != PCI_CLASS_BRIDGE_PCI) 107 continue; 108 109 vendor = read_pci_config(num, slot, func, 110 PCI_VENDOR_ID); 111 vendor &= 0xffff; 112 113 for (i = 0; early_qrk[i].f; i++) 114 if (early_qrk[i].vendor == vendor) { 115 early_qrk[i].f(); 116 return; 117 } 118 119 type = read_pci_config_byte(num, slot, func, 120 PCI_HEADER_TYPE); 121 if (!(type & 0x80)) 122 break; 123 } 124 } 125 } 126} 127