Commit | Line | Data |
---|---|---|
dfa4698c AK |
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> | |
814c5f1f | 15 | #include <drm/i915_drm.h> |
dfa4698c | 16 | #include <asm/pci-direct.h> |
dfa4698c | 17 | #include <asm/dma.h> |
54ef3400 AK |
18 | #include <asm/io_apic.h> |
19 | #include <asm/apic.h> | |
62187910 | 20 | #include <asm/hpet.h> |
46a7fa27 | 21 | #include <asm/iommu.h> |
1d9b16d1 | 22 | #include <asm/gart.h> |
03bbcb2e | 23 | #include <asm/irq_remapping.h> |
dfa4698c | 24 | |
c6b48324 NH |
25 | static void __init fix_hypertransport_config(int num, int slot, int func) |
26 | { | |
27 | u32 htcfg; | |
28 | /* | |
29 | * we found a hypertransport bus | |
30 | * make sure that we are broadcasting | |
31 | * interrupts to all cpus on the ht bus | |
32 | * if we're using extended apic ids | |
33 | */ | |
34 | htcfg = read_pci_config(num, slot, func, 0x68); | |
35 | if (htcfg & (1 << 18)) { | |
7bcbc78d NH |
36 | printk(KERN_INFO "Detected use of extended apic ids " |
37 | "on hypertransport bus\n"); | |
c6b48324 | 38 | if ((htcfg & (1 << 17)) == 0) { |
7bcbc78d NH |
39 | printk(KERN_INFO "Enabling hypertransport extended " |
40 | "apic interrupt broadcast\n"); | |
41 | printk(KERN_INFO "Note this is a bios bug, " | |
42 | "please contact your hw vendor\n"); | |
c6b48324 NH |
43 | htcfg |= (1 << 17); |
44 | write_pci_config(num, slot, func, 0x68, htcfg); | |
45 | } | |
46 | } | |
47 | ||
48 | ||
49 | } | |
50 | ||
51 | static void __init via_bugs(int num, int slot, int func) | |
dfa4698c | 52 | { |
966396d3 | 53 | #ifdef CONFIG_GART_IOMMU |
c987d12f | 54 | if ((max_pfn > MAX_DMA32_PFN || force_iommu) && |
0440d4c0 | 55 | !gart_iommu_aperture_allowed) { |
dfa4698c | 56 | printk(KERN_INFO |
54ef3400 AK |
57 | "Looks like a VIA chipset. Disabling IOMMU." |
58 | " Override with iommu=allowed\n"); | |
0440d4c0 | 59 | gart_iommu_aperture_disabled = 1; |
dfa4698c AK |
60 | } |
61 | #endif | |
62 | } | |
63 | ||
64 | #ifdef CONFIG_ACPI | |
03d0d20e | 65 | #ifdef CONFIG_X86_IO_APIC |
dfa4698c | 66 | |
15a58ed1 | 67 | static int __init nvidia_hpet_check(struct acpi_table_header *header) |
dfa4698c | 68 | { |
dfa4698c AK |
69 | return 0; |
70 | } | |
03d0d20e JG |
71 | #endif /* CONFIG_X86_IO_APIC */ |
72 | #endif /* CONFIG_ACPI */ | |
dfa4698c | 73 | |
c6b48324 | 74 | static void __init nvidia_bugs(int num, int slot, int func) |
dfa4698c AK |
75 | { |
76 | #ifdef CONFIG_ACPI | |
54ef3400 | 77 | #ifdef CONFIG_X86_IO_APIC |
dfa4698c AK |
78 | /* |
79 | * All timer overrides on Nvidia are | |
80 | * wrong unless HPET is enabled. | |
fa18f477 AK |
81 | * Unfortunately that's not true on many Asus boards. |
82 | * We don't know yet how to detect this automatically, but | |
83 | * at least allow a command line override. | |
dfa4698c | 84 | */ |
fa18f477 AK |
85 | if (acpi_use_timer_override) |
86 | return; | |
87 | ||
fe699336 | 88 | if (acpi_table_parse(ACPI_SIG_HPET, nvidia_hpet_check)) { |
dfa4698c AK |
89 | acpi_skip_timer_override = 1; |
90 | printk(KERN_INFO "Nvidia board " | |
91 | "detected. Ignoring ACPI " | |
92 | "timer override.\n"); | |
fa18f477 AK |
93 | printk(KERN_INFO "If you got timer trouble " |
94 | "try acpi_use_timer_override\n"); | |
dfa4698c | 95 | } |
54ef3400 | 96 | #endif |
dfa4698c AK |
97 | #endif |
98 | /* RED-PEN skip them on mptables too? */ | |
99 | ||
100 | } | |
101 | ||
26adcfbf AH |
102 | #if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC) |
103 | static u32 __init ati_ixp4x0_rev(int num, int slot, int func) | |
33fb0e4e AH |
104 | { |
105 | u32 d; | |
106 | u8 b; | |
107 | ||
108 | b = read_pci_config_byte(num, slot, func, 0xac); | |
109 | b &= ~(1<<5); | |
110 | write_pci_config_byte(num, slot, func, 0xac, b); | |
111 | ||
112 | d = read_pci_config(num, slot, func, 0x70); | |
113 | d |= 1<<8; | |
114 | write_pci_config(num, slot, func, 0x70, d); | |
115 | ||
116 | d = read_pci_config(num, slot, func, 0x8); | |
117 | d &= 0xff; | |
118 | return d; | |
119 | } | |
120 | ||
121 | static void __init ati_bugs(int num, int slot, int func) | |
122 | { | |
33fb0e4e AH |
123 | u32 d; |
124 | u8 b; | |
125 | ||
126 | if (acpi_use_timer_override) | |
127 | return; | |
128 | ||
129 | d = ati_ixp4x0_rev(num, slot, func); | |
130 | if (d < 0x82) | |
131 | acpi_skip_timer_override = 1; | |
132 | else { | |
133 | /* check for IRQ0 interrupt swap */ | |
134 | outb(0x72, 0xcd6); b = inb(0xcd7); | |
135 | if (!(b & 0x2)) | |
136 | acpi_skip_timer_override = 1; | |
137 | } | |
138 | ||
139 | if (acpi_skip_timer_override) { | |
140 | printk(KERN_INFO "SB4X0 revision 0x%x\n", d); | |
141 | printk(KERN_INFO "Ignoring ACPI timer override.\n"); | |
142 | printk(KERN_INFO "If you got timer trouble " | |
143 | "try acpi_use_timer_override\n"); | |
144 | } | |
33fb0e4e AH |
145 | } |
146 | ||
26adcfbf AH |
147 | static u32 __init ati_sbx00_rev(int num, int slot, int func) |
148 | { | |
7f74f8f2 | 149 | u32 d; |
26adcfbf | 150 | |
26adcfbf AH |
151 | d = read_pci_config(num, slot, func, 0x8); |
152 | d &= 0xff; | |
26adcfbf AH |
153 | |
154 | return d; | |
155 | } | |
156 | ||
157 | static void __init ati_bugs_contd(int num, int slot, int func) | |
158 | { | |
159 | u32 d, rev; | |
160 | ||
26adcfbf | 161 | rev = ati_sbx00_rev(num, slot, func); |
7f74f8f2 AH |
162 | if (rev >= 0x40) |
163 | acpi_fix_pin2_polarity = 1; | |
164 | ||
1d3e09a3 AH |
165 | /* |
166 | * SB600: revisions 0x11, 0x12, 0x13, 0x14, ... | |
167 | * SB700: revisions 0x39, 0x3a, ... | |
168 | * SB800: revisions 0x40, 0x41, ... | |
169 | */ | |
170 | if (rev >= 0x39) | |
26adcfbf AH |
171 | return; |
172 | ||
7f74f8f2 AH |
173 | if (acpi_use_timer_override) |
174 | return; | |
175 | ||
26adcfbf AH |
176 | /* check for IRQ0 interrupt swap */ |
177 | d = read_pci_config(num, slot, func, 0x64); | |
178 | if (!(d & (1<<14))) | |
179 | acpi_skip_timer_override = 1; | |
180 | ||
181 | if (acpi_skip_timer_override) { | |
182 | printk(KERN_INFO "SB600 revision 0x%x\n", rev); | |
183 | printk(KERN_INFO "Ignoring ACPI timer override.\n"); | |
184 | printk(KERN_INFO "If you got timer trouble " | |
185 | "try acpi_use_timer_override\n"); | |
186 | } | |
187 | } | |
188 | #else | |
189 | static void __init ati_bugs(int num, int slot, int func) | |
190 | { | |
191 | } | |
192 | ||
193 | static void __init ati_bugs_contd(int num, int slot, int func) | |
194 | { | |
195 | } | |
196 | #endif | |
197 | ||
03bbcb2e NH |
198 | static void __init intel_remapping_check(int num, int slot, int func) |
199 | { | |
200 | u8 revision; | |
803075db | 201 | u16 device; |
03bbcb2e | 202 | |
803075db | 203 | device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID); |
03bbcb2e NH |
204 | revision = read_pci_config_byte(num, slot, func, PCI_REVISION_ID); |
205 | ||
206 | /* | |
6f8a1b33 NH |
207 | * Revision <= 13 of all triggering devices id in this quirk |
208 | * have a problem draining interrupts when irq remapping is | |
209 | * enabled, and should be flagged as broken. Additionally | |
210 | * revision 0x22 of device id 0x3405 has this problem. | |
03bbcb2e | 211 | */ |
6f8a1b33 | 212 | if (revision <= 0x13) |
03bbcb2e | 213 | set_irq_remapping_broken(); |
6f8a1b33 | 214 | else if (device == 0x3405 && revision == 0x22) |
803075db | 215 | set_irq_remapping_broken(); |
03bbcb2e NH |
216 | } |
217 | ||
814c5f1f JB |
218 | /* |
219 | * Systems with Intel graphics controllers set aside memory exclusively | |
220 | * for gfx driver use. This memory is not marked in the E820 as reserved | |
221 | * or as RAM, and so is subject to overlap from E820 manipulation later | |
222 | * in the boot process. On some systems, MMIO space is allocated on top, | |
223 | * despite the efforts of the "RAM buffer" approach, which simply rounds | |
224 | * memory boundaries up to 64M to try to catch space that may decode | |
225 | * as RAM and so is not suitable for MMIO. | |
226 | * | |
227 | * And yes, so far on current devices the base addr is always under 4G. | |
228 | */ | |
52ca7045 | 229 | static u32 __init intel_stolen_base(int num, int slot, int func, size_t stolen_size) |
814c5f1f JB |
230 | { |
231 | u32 base; | |
232 | ||
233 | /* | |
234 | * For the PCI IDs in this quirk, the stolen base is always | |
235 | * in 0x5c, aka the BDSM register (yes that's really what | |
236 | * it's called). | |
237 | */ | |
238 | base = read_pci_config(num, slot, func, 0x5c); | |
239 | base &= ~((1<<20) - 1); | |
240 | ||
241 | return base; | |
242 | } | |
243 | ||
86e58762 | 244 | #define KB(x) ((x) * 1024UL) |
814c5f1f JB |
245 | #define MB(x) (KB (KB (x))) |
246 | #define GB(x) (MB (KB (x))) | |
247 | ||
a4dff769 VS |
248 | static size_t __init i830_tseg_size(void) |
249 | { | |
250 | u8 tmp = read_pci_config_byte(0, 0, 0, I830_ESMRAMC); | |
251 | ||
252 | if (!(tmp & TSEG_ENABLE)) | |
253 | return 0; | |
254 | ||
255 | if (tmp & I830_TSEG_SIZE_1M) | |
256 | return MB(1); | |
257 | else | |
258 | return KB(512); | |
259 | } | |
260 | ||
261 | static size_t __init i845_tseg_size(void) | |
262 | { | |
263 | u8 tmp = read_pci_config_byte(0, 0, 0, I845_ESMRAMC); | |
264 | ||
265 | if (!(tmp & TSEG_ENABLE)) | |
266 | return 0; | |
267 | ||
268 | switch (tmp & I845_TSEG_SIZE_MASK) { | |
269 | case I845_TSEG_SIZE_512K: | |
270 | return KB(512); | |
271 | case I845_TSEG_SIZE_1M: | |
272 | return MB(1); | |
273 | default: | |
274 | WARN_ON(1); | |
275 | return 0; | |
276 | } | |
277 | } | |
278 | ||
279 | static size_t __init i85x_tseg_size(void) | |
280 | { | |
281 | u8 tmp = read_pci_config_byte(0, 0, 0, I85X_ESMRAMC); | |
282 | ||
283 | if (!(tmp & TSEG_ENABLE)) | |
284 | return 0; | |
285 | ||
286 | return MB(1); | |
287 | } | |
288 | ||
289 | static size_t __init i830_mem_size(void) | |
290 | { | |
291 | return read_pci_config_byte(0, 0, 0, I830_DRB3) * MB(32); | |
292 | } | |
293 | ||
294 | static size_t __init i85x_mem_size(void) | |
295 | { | |
296 | return read_pci_config_byte(0, 0, 1, I85X_DRB3) * MB(32); | |
297 | } | |
298 | ||
299 | /* | |
300 | * On 830/845/85x the stolen memory base isn't available in any | |
301 | * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size. | |
302 | */ | |
303 | static u32 __init i830_stolen_base(int num, int slot, int func, size_t stolen_size) | |
304 | { | |
305 | return i830_mem_size() - i830_tseg_size() - stolen_size; | |
306 | } | |
307 | ||
308 | static u32 __init i845_stolen_base(int num, int slot, int func, size_t stolen_size) | |
309 | { | |
310 | return i830_mem_size() - i845_tseg_size() - stolen_size; | |
311 | } | |
312 | ||
313 | static u32 __init i85x_stolen_base(int num, int slot, int func, size_t stolen_size) | |
314 | { | |
315 | return i85x_mem_size() - i85x_tseg_size() - stolen_size; | |
316 | } | |
317 | ||
318 | static u32 __init i865_stolen_base(int num, int slot, int func, size_t stolen_size) | |
319 | { | |
320 | /* | |
321 | * FIXME is the graphics stolen memory region | |
322 | * always at TOUD? Ie. is it always the last | |
323 | * one to be allocated by the BIOS? | |
324 | */ | |
325 | return read_pci_config_16(0, 0, 0, I865_TOUD) << 16; | |
326 | } | |
327 | ||
328 | static size_t __init i830_stolen_size(int num, int slot, int func) | |
329 | { | |
330 | size_t stolen_size; | |
331 | u16 gmch_ctrl; | |
332 | ||
333 | gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL); | |
334 | ||
335 | switch (gmch_ctrl & I830_GMCH_GMS_MASK) { | |
336 | case I830_GMCH_GMS_STOLEN_512: | |
337 | stolen_size = KB(512); | |
338 | break; | |
339 | case I830_GMCH_GMS_STOLEN_1024: | |
340 | stolen_size = MB(1); | |
341 | break; | |
342 | case I830_GMCH_GMS_STOLEN_8192: | |
343 | stolen_size = MB(8); | |
344 | break; | |
345 | case I830_GMCH_GMS_LOCAL: | |
346 | /* local memory isn't part of the normal address space */ | |
347 | stolen_size = 0; | |
348 | break; | |
349 | default: | |
350 | return 0; | |
351 | } | |
352 | ||
353 | return stolen_size; | |
354 | } | |
355 | ||
814c5f1f JB |
356 | static size_t __init gen3_stolen_size(int num, int slot, int func) |
357 | { | |
358 | size_t stolen_size; | |
359 | u16 gmch_ctrl; | |
360 | ||
361 | gmch_ctrl = read_pci_config_16(0, 0, 0, I830_GMCH_CTRL); | |
362 | ||
363 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { | |
364 | case I855_GMCH_GMS_STOLEN_1M: | |
365 | stolen_size = MB(1); | |
366 | break; | |
367 | case I855_GMCH_GMS_STOLEN_4M: | |
368 | stolen_size = MB(4); | |
369 | break; | |
370 | case I855_GMCH_GMS_STOLEN_8M: | |
371 | stolen_size = MB(8); | |
372 | break; | |
373 | case I855_GMCH_GMS_STOLEN_16M: | |
374 | stolen_size = MB(16); | |
375 | break; | |
376 | case I855_GMCH_GMS_STOLEN_32M: | |
377 | stolen_size = MB(32); | |
378 | break; | |
379 | case I915_GMCH_GMS_STOLEN_48M: | |
380 | stolen_size = MB(48); | |
381 | break; | |
382 | case I915_GMCH_GMS_STOLEN_64M: | |
383 | stolen_size = MB(64); | |
384 | break; | |
385 | case G33_GMCH_GMS_STOLEN_128M: | |
386 | stolen_size = MB(128); | |
387 | break; | |
388 | case G33_GMCH_GMS_STOLEN_256M: | |
389 | stolen_size = MB(256); | |
390 | break; | |
391 | case INTEL_GMCH_GMS_STOLEN_96M: | |
392 | stolen_size = MB(96); | |
393 | break; | |
394 | case INTEL_GMCH_GMS_STOLEN_160M: | |
395 | stolen_size = MB(160); | |
396 | break; | |
397 | case INTEL_GMCH_GMS_STOLEN_224M: | |
398 | stolen_size = MB(224); | |
399 | break; | |
400 | case INTEL_GMCH_GMS_STOLEN_352M: | |
401 | stolen_size = MB(352); | |
402 | break; | |
403 | default: | |
404 | stolen_size = 0; | |
405 | break; | |
406 | } | |
407 | ||
408 | return stolen_size; | |
409 | } | |
410 | ||
411 | static size_t __init gen6_stolen_size(int num, int slot, int func) | |
412 | { | |
413 | u16 gmch_ctrl; | |
414 | ||
415 | gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); | |
416 | gmch_ctrl >>= SNB_GMCH_GMS_SHIFT; | |
417 | gmch_ctrl &= SNB_GMCH_GMS_MASK; | |
418 | ||
419 | return gmch_ctrl << 25; /* 32 MB units */ | |
420 | } | |
421 | ||
36dfcea4 | 422 | static size_t __init gen8_stolen_size(int num, int slot, int func) |
9459d252 BW |
423 | { |
424 | u16 gmch_ctrl; | |
425 | ||
426 | gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); | |
427 | gmch_ctrl >>= BDW_GMCH_GMS_SHIFT; | |
428 | gmch_ctrl &= BDW_GMCH_GMS_MASK; | |
429 | return gmch_ctrl << 25; /* 32 MB units */ | |
430 | } | |
431 | ||
3e3b2c39 DL |
432 | static size_t __init chv_stolen_size(int num, int slot, int func) |
433 | { | |
434 | u16 gmch_ctrl; | |
435 | ||
436 | gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); | |
437 | gmch_ctrl >>= SNB_GMCH_GMS_SHIFT; | |
438 | gmch_ctrl &= SNB_GMCH_GMS_MASK; | |
439 | ||
440 | /* | |
441 | * 0x0 to 0x10: 32MB increments starting at 0MB | |
442 | * 0x11 to 0x16: 4MB increments starting at 8MB | |
443 | * 0x17 to 0x1d: 4MB increments start at 36MB | |
444 | */ | |
445 | if (gmch_ctrl < 0x11) | |
446 | return gmch_ctrl << 25; | |
447 | else if (gmch_ctrl < 0x17) | |
448 | return (gmch_ctrl - 0x11 + 2) << 22; | |
449 | else | |
450 | return (gmch_ctrl - 0x17 + 9) << 22; | |
451 | } | |
52ca7045 VS |
452 | |
453 | struct intel_stolen_funcs { | |
454 | size_t (*size)(int num, int slot, int func); | |
455 | u32 (*base)(int num, int slot, int func, size_t size); | |
456 | }; | |
457 | ||
66375014 DL |
458 | static size_t __init gen9_stolen_size(int num, int slot, int func) |
459 | { | |
460 | u16 gmch_ctrl; | |
461 | ||
462 | gmch_ctrl = read_pci_config_16(num, slot, func, SNB_GMCH_CTRL); | |
463 | gmch_ctrl >>= BDW_GMCH_GMS_SHIFT; | |
464 | gmch_ctrl &= BDW_GMCH_GMS_MASK; | |
465 | ||
466 | if (gmch_ctrl < 0xf0) | |
467 | return gmch_ctrl << 25; /* 32 MB units */ | |
468 | else | |
469 | /* 4MB increments starting at 0xf0 for 4MB */ | |
470 | return (gmch_ctrl - 0xf0 + 1) << 22; | |
471 | } | |
472 | ||
473 | typedef size_t (*stolen_size_fn)(int num, int slot, int func); | |
474 | ||
36dfcea4 | 475 | static const struct intel_stolen_funcs i830_stolen_funcs __initconst = { |
a4dff769 VS |
476 | .base = i830_stolen_base, |
477 | .size = i830_stolen_size, | |
478 | }; | |
479 | ||
36dfcea4 | 480 | static const struct intel_stolen_funcs i845_stolen_funcs __initconst = { |
a4dff769 VS |
481 | .base = i845_stolen_base, |
482 | .size = i830_stolen_size, | |
483 | }; | |
484 | ||
36dfcea4 | 485 | static const struct intel_stolen_funcs i85x_stolen_funcs __initconst = { |
a4dff769 VS |
486 | .base = i85x_stolen_base, |
487 | .size = gen3_stolen_size, | |
488 | }; | |
489 | ||
36dfcea4 | 490 | static const struct intel_stolen_funcs i865_stolen_funcs __initconst = { |
a4dff769 VS |
491 | .base = i865_stolen_base, |
492 | .size = gen3_stolen_size, | |
493 | }; | |
494 | ||
36dfcea4 | 495 | static const struct intel_stolen_funcs gen3_stolen_funcs __initconst = { |
52ca7045 VS |
496 | .base = intel_stolen_base, |
497 | .size = gen3_stolen_size, | |
498 | }; | |
499 | ||
36dfcea4 | 500 | static const struct intel_stolen_funcs gen6_stolen_funcs __initconst = { |
52ca7045 VS |
501 | .base = intel_stolen_base, |
502 | .size = gen6_stolen_size, | |
503 | }; | |
504 | ||
36dfcea4 | 505 | static const struct intel_stolen_funcs gen8_stolen_funcs __initconst = { |
52ca7045 VS |
506 | .base = intel_stolen_base, |
507 | .size = gen8_stolen_size, | |
508 | }; | |
814c5f1f | 509 | |
66375014 DL |
510 | static const struct intel_stolen_funcs gen9_stolen_funcs __initconst = { |
511 | .base = intel_stolen_base, | |
512 | .size = gen9_stolen_size, | |
513 | }; | |
514 | ||
36dfcea4 | 515 | static const struct intel_stolen_funcs chv_stolen_funcs __initconst = { |
3e3b2c39 DL |
516 | .base = intel_stolen_base, |
517 | .size = chv_stolen_size, | |
518 | }; | |
519 | ||
36dfcea4 | 520 | static const struct pci_device_id intel_stolen_ids[] __initconst = { |
a4dff769 VS |
521 | INTEL_I830_IDS(&i830_stolen_funcs), |
522 | INTEL_I845G_IDS(&i845_stolen_funcs), | |
523 | INTEL_I85X_IDS(&i85x_stolen_funcs), | |
524 | INTEL_I865G_IDS(&i865_stolen_funcs), | |
52ca7045 VS |
525 | INTEL_I915G_IDS(&gen3_stolen_funcs), |
526 | INTEL_I915GM_IDS(&gen3_stolen_funcs), | |
527 | INTEL_I945G_IDS(&gen3_stolen_funcs), | |
528 | INTEL_I945GM_IDS(&gen3_stolen_funcs), | |
529 | INTEL_VLV_M_IDS(&gen6_stolen_funcs), | |
530 | INTEL_VLV_D_IDS(&gen6_stolen_funcs), | |
531 | INTEL_PINEVIEW_IDS(&gen3_stolen_funcs), | |
532 | INTEL_I965G_IDS(&gen3_stolen_funcs), | |
533 | INTEL_G33_IDS(&gen3_stolen_funcs), | |
534 | INTEL_I965GM_IDS(&gen3_stolen_funcs), | |
535 | INTEL_GM45_IDS(&gen3_stolen_funcs), | |
536 | INTEL_G45_IDS(&gen3_stolen_funcs), | |
537 | INTEL_IRONLAKE_D_IDS(&gen3_stolen_funcs), | |
538 | INTEL_IRONLAKE_M_IDS(&gen3_stolen_funcs), | |
539 | INTEL_SNB_D_IDS(&gen6_stolen_funcs), | |
540 | INTEL_SNB_M_IDS(&gen6_stolen_funcs), | |
541 | INTEL_IVB_M_IDS(&gen6_stolen_funcs), | |
542 | INTEL_IVB_D_IDS(&gen6_stolen_funcs), | |
543 | INTEL_HSW_D_IDS(&gen6_stolen_funcs), | |
544 | INTEL_HSW_M_IDS(&gen6_stolen_funcs), | |
545 | INTEL_BDW_M_IDS(&gen8_stolen_funcs), | |
3e3b2c39 DL |
546 | INTEL_BDW_D_IDS(&gen8_stolen_funcs), |
547 | INTEL_CHV_IDS(&chv_stolen_funcs), | |
66375014 | 548 | INTEL_SKL_IDS(&gen9_stolen_funcs), |
31d4dcf7 | 549 | INTEL_BXT_IDS(&gen9_stolen_funcs), |
00ce5c8a | 550 | INTEL_KBL_IDS(&gen9_stolen_funcs), |
814c5f1f JB |
551 | }; |
552 | ||
553 | static void __init intel_graphics_stolen(int num, int slot, int func) | |
554 | { | |
555 | size_t size; | |
556 | int i; | |
557 | u32 start; | |
558 | u16 device, subvendor, subdevice; | |
559 | ||
560 | device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID); | |
561 | subvendor = read_pci_config_16(num, slot, func, | |
562 | PCI_SUBSYSTEM_VENDOR_ID); | |
563 | subdevice = read_pci_config_16(num, slot, func, PCI_SUBSYSTEM_ID); | |
564 | ||
565 | for (i = 0; i < ARRAY_SIZE(intel_stolen_ids); i++) { | |
566 | if (intel_stolen_ids[i].device == device) { | |
52ca7045 VS |
567 | const struct intel_stolen_funcs *stolen_funcs = |
568 | (const struct intel_stolen_funcs *)intel_stolen_ids[i].driver_data; | |
569 | size = stolen_funcs->size(num, slot, func); | |
570 | start = stolen_funcs->base(num, slot, func, size); | |
814c5f1f | 571 | if (size && start) { |
c71ef7b3 VS |
572 | printk(KERN_INFO "Reserving Intel graphics stolen memory at 0x%x-0x%x\n", |
573 | start, start + (u32)size - 1); | |
814c5f1f JB |
574 | /* Mark this space as reserved */ |
575 | e820_add_region(start, size, E820_RESERVED); | |
576 | sanitize_e820_map(e820.map, | |
577 | ARRAY_SIZE(e820.map), | |
578 | &e820.nr_map); | |
579 | } | |
580 | return; | |
581 | } | |
582 | } | |
583 | } | |
584 | ||
62187910 FT |
585 | static void __init force_disable_hpet(int num, int slot, int func) |
586 | { | |
587 | #ifdef CONFIG_HPET_TIMER | |
3d45ac4b | 588 | boot_hpet_disable = true; |
62187910 FT |
589 | pr_info("x86/hpet: Will disable the HPET for this platform because it's not reliable\n"); |
590 | #endif | |
591 | } | |
592 | ||
593 | ||
c6b48324 NH |
594 | #define QFLAG_APPLY_ONCE 0x1 |
595 | #define QFLAG_APPLIED 0x2 | |
596 | #define QFLAG_DONE (QFLAG_APPLY_ONCE|QFLAG_APPLIED) | |
dfa4698c | 597 | struct chipset { |
c6b48324 NH |
598 | u32 vendor; |
599 | u32 device; | |
600 | u32 class; | |
601 | u32 class_mask; | |
602 | u32 flags; | |
603 | void (*f)(int num, int slot, int func); | |
dfa4698c AK |
604 | }; |
605 | ||
8659c406 AK |
606 | /* |
607 | * Only works for devices on the root bus. If you add any devices | |
608 | * not on bus 0 readd another loop level in early_quirks(). But | |
609 | * be careful because at least the Nvidia quirk here relies on | |
610 | * only matching on bus 0. | |
611 | */ | |
c993c735 | 612 | static struct chipset early_qrk[] __initdata = { |
c6b48324 NH |
613 | { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, |
614 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs }, | |
615 | { PCI_VENDOR_ID_VIA, PCI_ANY_ID, | |
616 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, via_bugs }, | |
c6b48324 NH |
617 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, |
618 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, | |
33fb0e4e AH |
619 | { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, |
620 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs }, | |
26adcfbf AH |
621 | { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, |
622 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, | |
03bbcb2e NH |
623 | { PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST, |
624 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | |
803075db NH |
625 | { PCI_VENDOR_ID_INTEL, 0x3405, PCI_CLASS_BRIDGE_HOST, |
626 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | |
03bbcb2e NH |
627 | { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, |
628 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | |
814c5f1f JB |
629 | { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, PCI_ANY_ID, |
630 | QFLAG_APPLY_ONCE, intel_graphics_stolen }, | |
62187910 | 631 | /* |
b58d9307 FT |
632 | * HPET on the current version of the Baytrail platform has accuracy |
633 | * problems: it will halt in deep idle state - so we disable it. | |
634 | * | |
635 | * More details can be found in section 18.10.1.3 of the datasheet: | |
636 | * | |
637 | * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/atom-z8000-datasheet-vol-1.pdf | |
62187910 FT |
638 | */ |
639 | { PCI_VENDOR_ID_INTEL, 0x0f00, | |
640 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet}, | |
dfa4698c AK |
641 | {} |
642 | }; | |
643 | ||
15650a2f JB |
644 | /** |
645 | * check_dev_quirk - apply early quirks to a given PCI device | |
646 | * @num: bus number | |
647 | * @slot: slot number | |
648 | * @func: PCI function | |
649 | * | |
650 | * Check the vendor & device ID against the early quirks table. | |
651 | * | |
652 | * If the device is single function, let early_quirks() know so we don't | |
653 | * poke at this device again. | |
654 | */ | |
655 | static int __init check_dev_quirk(int num, int slot, int func) | |
7bcbc78d NH |
656 | { |
657 | u16 class; | |
658 | u16 vendor; | |
659 | u16 device; | |
660 | u8 type; | |
661 | int i; | |
662 | ||
663 | class = read_pci_config_16(num, slot, func, PCI_CLASS_DEVICE); | |
664 | ||
665 | if (class == 0xffff) | |
15650a2f | 666 | return -1; /* no class, treat as single function */ |
7bcbc78d NH |
667 | |
668 | vendor = read_pci_config_16(num, slot, func, PCI_VENDOR_ID); | |
669 | ||
670 | device = read_pci_config_16(num, slot, func, PCI_DEVICE_ID); | |
671 | ||
672 | for (i = 0; early_qrk[i].f != NULL; i++) { | |
673 | if (((early_qrk[i].vendor == PCI_ANY_ID) || | |
674 | (early_qrk[i].vendor == vendor)) && | |
675 | ((early_qrk[i].device == PCI_ANY_ID) || | |
676 | (early_qrk[i].device == device)) && | |
677 | (!((early_qrk[i].class ^ class) & | |
678 | early_qrk[i].class_mask))) { | |
679 | if ((early_qrk[i].flags & | |
680 | QFLAG_DONE) != QFLAG_DONE) | |
681 | early_qrk[i].f(num, slot, func); | |
682 | early_qrk[i].flags |= QFLAG_APPLIED; | |
683 | } | |
684 | } | |
685 | ||
686 | type = read_pci_config_byte(num, slot, func, | |
687 | PCI_HEADER_TYPE); | |
688 | if (!(type & 0x80)) | |
15650a2f JB |
689 | return -1; |
690 | ||
691 | return 0; | |
7bcbc78d NH |
692 | } |
693 | ||
dfa4698c AK |
694 | void __init early_quirks(void) |
695 | { | |
8659c406 | 696 | int slot, func; |
0637a70a AK |
697 | |
698 | if (!early_pci_allowed()) | |
699 | return; | |
700 | ||
dfa4698c | 701 | /* Poor man's PCI discovery */ |
8659c406 AK |
702 | /* Only scan the root bus */ |
703 | for (slot = 0; slot < 32; slot++) | |
704 | for (func = 0; func < 8; func++) { | |
705 | /* Only probe function 0 on single fn devices */ | |
706 | if (check_dev_quirk(0, slot, func)) | |
707 | break; | |
708 | } | |
dfa4698c | 709 | } |