1 /* 2 * This file contains work-arounds for x86 and x86_64 platform bugs. 3 */ 4 #include <linux/pci.h> 5 #include <linux/irq.h> 6 7 #include <asm/hpet.h> 8 9 #if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI) 10 11 static void __devinit quirk_intel_irqbalance(struct pci_dev *dev) 12 { 13 u8 config, rev; 14 u32 word; 15 16 /* BIOS may enable hardware IRQ balancing for 17 * E7520/E7320/E7525(revision ID 0x9 and below) 18 * based platforms. 19 * Disable SW irqbalance/affinity on those platforms. 20 */ 21 pci_read_config_byte(dev, PCI_CLASS_REVISION, &rev); 22 if (rev > 0x9) 23 return; 24 25 /* enable access to config space*/ 26 pci_read_config_byte(dev, 0xf4, &config); 27 pci_write_config_byte(dev, 0xf4, config|0x2); 28 29 /* read xTPR register */ 30 raw_pci_ops->read(0, 0, 0x40, 0x4c, 2, &word); 31 32 if (!(word & (1 << 13))) { 33 printk(KERN_INFO "Intel E7520/7320/7525 detected. " 34 "Disabling irq balancing and affinity\n"); 35 #ifdef CONFIG_IRQBALANCE 36 irqbalance_disable(""); 37 #endif 38 noirqdebug_setup(""); 39 #ifdef CONFIG_PROC_FS 40 no_irq_affinity = 1; 41 #endif 42 } 43 44 /* put back the original value for config space*/ 45 if (!(config & 0x2)) 46 pci_write_config_byte(dev, 0xf4, config); 47 } 48 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH, quirk_intel_irqbalance); 49 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH, quirk_intel_irqbalance); 50 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, quirk_intel_irqbalance); 51 #endif 52 53 #if defined(CONFIG_HPET_TIMER) 54 unsigned long force_hpet_address; 55 56 static enum { 57 NONE_FORCE_HPET_RESUME, 58 OLD_ICH_FORCE_HPET_RESUME, 59 ICH_FORCE_HPET_RESUME 60 } force_hpet_resume_type; 61 62 static void __iomem *rcba_base; 63 64 static void ich_force_hpet_resume(void) 65 { 66 u32 val; 67 68 if (!force_hpet_address) 69 return; 70 71 if (rcba_base == NULL) 72 BUG(); 73 74 /* read the Function Disable register, dword mode only */ 75 val = readl(rcba_base + 0x3404); 76 if (!(val & 0x80)) { 77 /* HPET disabled in HPTC. Trying to enable */ 78 writel(val | 0x80, rcba_base + 0x3404); 79 } 80 81 val = readl(rcba_base + 0x3404); 82 if (!(val & 0x80)) 83 BUG(); 84 else 85 printk(KERN_DEBUG "Force enabled HPET at resume\n"); 86 87 return; 88 } 89 90 static void ich_force_enable_hpet(struct pci_dev *dev) 91 { 92 u32 val; 93 u32 uninitialized_var(rcba); 94 int err = 0; 95 96 if (hpet_address || force_hpet_address) 97 return; 98 99 pci_read_config_dword(dev, 0xF0, &rcba); 100 rcba &= 0xFFFFC000; 101 if (rcba == 0) { 102 printk(KERN_DEBUG "RCBA disabled. Cannot force enable HPET\n"); 103 return; 104 } 105 106 /* use bits 31:14, 16 kB aligned */ 107 rcba_base = ioremap_nocache(rcba, 0x4000); 108 if (rcba_base == NULL) { 109 printk(KERN_DEBUG "ioremap failed. Cannot force enable HPET\n"); 110 return; 111 } 112 113 /* read the Function Disable register, dword mode only */ 114 val = readl(rcba_base + 0x3404); 115 116 if (val & 0x80) { 117 /* HPET is enabled in HPTC. Just not reported by BIOS */ 118 val = val & 0x3; 119 force_hpet_address = 0xFED00000 | (val << 12); 120 printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", 121 force_hpet_address); 122 iounmap(rcba_base); 123 return; 124 } 125 126 /* HPET disabled in HPTC. Trying to enable */ 127 writel(val | 0x80, rcba_base + 0x3404); 128 129 val = readl(rcba_base + 0x3404); 130 if (!(val & 0x80)) { 131 err = 1; 132 } else { 133 val = val & 0x3; 134 force_hpet_address = 0xFED00000 | (val << 12); 135 } 136 137 if (err) { 138 force_hpet_address = 0; 139 iounmap(rcba_base); 140 printk(KERN_DEBUG "Failed to force enable HPET\n"); 141 } else { 142 force_hpet_resume_type = ICH_FORCE_HPET_RESUME; 143 printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", 144 force_hpet_address); 145 } 146 } 147 148 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0, 149 ich_force_enable_hpet); 150 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, 151 ich_force_enable_hpet); 152 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, 153 ich_force_enable_hpet); 154 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, 155 ich_force_enable_hpet); 156 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31, 157 ich_force_enable_hpet); 158 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1, 159 ich_force_enable_hpet); 160 161 162 static struct pci_dev *cached_dev; 163 164 static void old_ich_force_hpet_resume(void) 165 { 166 u32 val; 167 u32 uninitialized_var(gen_cntl); 168 169 if (!force_hpet_address || !cached_dev) 170 return; 171 172 pci_read_config_dword(cached_dev, 0xD0, &gen_cntl); 173 gen_cntl &= (~(0x7 << 15)); 174 gen_cntl |= (0x4 << 15); 175 176 pci_write_config_dword(cached_dev, 0xD0, gen_cntl); 177 pci_read_config_dword(cached_dev, 0xD0, &gen_cntl); 178 val = gen_cntl >> 15; 179 val &= 0x7; 180 if (val == 0x4) 181 printk(KERN_DEBUG "Force enabled HPET at resume\n"); 182 else 183 BUG(); 184 } 185 186 static void old_ich_force_enable_hpet(struct pci_dev *dev) 187 { 188 u32 val; 189 u32 uninitialized_var(gen_cntl); 190 191 if (hpet_address || force_hpet_address) 192 return; 193 194 pci_read_config_dword(dev, 0xD0, &gen_cntl); 195 /* 196 * Bit 17 is HPET enable bit. 197 * Bit 16:15 control the HPET base address. 198 */ 199 val = gen_cntl >> 15; 200 val &= 0x7; 201 if (val & 0x4) { 202 val &= 0x3; 203 force_hpet_address = 0xFED00000 | (val << 12); 204 printk(KERN_DEBUG "HPET at base address 0x%lx\n", 205 force_hpet_address); 206 return; 207 } 208 209 /* 210 * HPET is disabled. Trying enabling at FED00000 and check 211 * whether it sticks 212 */ 213 gen_cntl &= (~(0x7 << 15)); 214 gen_cntl |= (0x4 << 15); 215 pci_write_config_dword(dev, 0xD0, gen_cntl); 216 217 pci_read_config_dword(dev, 0xD0, &gen_cntl); 218 219 val = gen_cntl >> 15; 220 val &= 0x7; 221 if (val & 0x4) { 222 /* HPET is enabled in HPTC. Just not reported by BIOS */ 223 val &= 0x3; 224 force_hpet_address = 0xFED00000 | (val << 12); 225 printk(KERN_DEBUG "Force enabled HPET at base address 0x%lx\n", 226 force_hpet_address); 227 cached_dev = dev; 228 force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME; 229 return; 230 } 231 232 printk(KERN_DEBUG "Failed to force enable HPET\n"); 233 } 234 235 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, 236 old_ich_force_enable_hpet); 237 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12, 238 old_ich_force_enable_hpet); 239 240 void force_hpet_resume(void) 241 { 242 switch (force_hpet_resume_type) { 243 case ICH_FORCE_HPET_RESUME: 244 return ich_force_hpet_resume(); 245 246 case OLD_ICH_FORCE_HPET_RESUME: 247 return old_ich_force_hpet_resume(); 248 249 default: 250 break; 251 } 252 } 253 254 #endif 255