| 1 | // SPDX-License-Identifier: GPL-2.0 | 
|---|
| 2 | /* Various workarounds for chipset bugs. | 
|---|
| 3 | This code runs very early and can't use the regular PCI subsystem | 
|---|
| 4 | The entries are keyed to PCI bridges which usually identify chipsets | 
|---|
| 5 | uniquely. | 
|---|
| 6 | This is only for whole classes of chipsets with specific problems which | 
|---|
| 7 | need early invasive action (e.g. before the timers are initialized). | 
|---|
| 8 | Most PCI device specific workarounds can be done later and should be | 
|---|
| 9 | in standard PCI quirks | 
|---|
| 10 | Mainboard specific bugs should be handled by DMI entries. | 
|---|
| 11 | CPU specific bugs in setup.c */ | 
|---|
| 12 |  | 
|---|
| 13 | #include <linux/pci.h> | 
|---|
| 14 | #include <linux/acpi.h> | 
|---|
| 15 | #include <linux/delay.h> | 
|---|
| 16 | #include <linux/pci_ids.h> | 
|---|
| 17 | #include <linux/bcma/bcma.h> | 
|---|
| 18 | #include <linux/bcma/bcma_regs.h> | 
|---|
| 19 | #include <linux/platform_data/x86/apple.h> | 
|---|
| 20 | #include <drm/intel/i915_drm.h> | 
|---|
| 21 | #include <drm/intel/pciids.h> | 
|---|
| 22 | #include <asm/pci-direct.h> | 
|---|
| 23 | #include <asm/dma.h> | 
|---|
| 24 | #include <asm/io_apic.h> | 
|---|
| 25 | #include <asm/apic.h> | 
|---|
| 26 | #include <asm/hpet.h> | 
|---|
| 27 | #include <asm/iommu.h> | 
|---|
| 28 | #include <asm/gart.h> | 
|---|
| 29 | #include <asm/irq_remapping.h> | 
|---|
| 30 | #include <asm/early_ioremap.h> | 
|---|
| 31 |  | 
|---|
| 32 | static void __init fix_hypertransport_config(int num, int slot, int func) | 
|---|
| 33 | { | 
|---|
| 34 | u32 htcfg; | 
|---|
| 35 | /* | 
|---|
| 36 | * we found a hypertransport bus | 
|---|
| 37 | * make sure that we are broadcasting | 
|---|
| 38 | * interrupts to all cpus on the ht bus | 
|---|
| 39 | * if we're using extended apic ids | 
|---|
| 40 | */ | 
|---|
| 41 | htcfg = read_pci_config(bus: num, slot, func, offset: 0x68); | 
|---|
| 42 | if (htcfg & (1 << 18)) { | 
|---|
| 43 | printk(KERN_INFO "Detected use of extended apic ids " | 
|---|
| 44 | "on hypertransport bus\n"); | 
|---|
| 45 | if ((htcfg & (1 << 17)) == 0) { | 
|---|
| 46 | printk(KERN_INFO "Enabling hypertransport extended " | 
|---|
| 47 | "apic interrupt broadcast\n"); | 
|---|
| 48 | printk(KERN_INFO "Note this is a bios bug, " | 
|---|
| 49 | "please contact your hw vendor\n"); | 
|---|
| 50 | htcfg |= (1 << 17); | 
|---|
| 51 | write_pci_config(bus: num, slot, func, offset: 0x68, val: htcfg); | 
|---|
| 52 | } | 
|---|
| 53 | } | 
|---|
| 54 |  | 
|---|
| 55 |  | 
|---|
| 56 | } | 
|---|
| 57 |  | 
|---|
| 58 | static void __init via_bugs(int  num, int slot, int func) | 
|---|
| 59 | { | 
|---|
| 60 | #ifdef CONFIG_GART_IOMMU | 
|---|
| 61 | if ((max_pfn > MAX_DMA32_PFN ||  force_iommu) && | 
|---|
| 62 | !gart_iommu_aperture_allowed) { | 
|---|
| 63 | printk(KERN_INFO | 
|---|
| 64 | "Looks like a VIA chipset. Disabling IOMMU." | 
|---|
| 65 | " Override with iommu=allowed\n"); | 
|---|
| 66 | gart_iommu_aperture_disabled = 1; | 
|---|
| 67 | } | 
|---|
| 68 | #endif | 
|---|
| 69 | } | 
|---|
| 70 |  | 
|---|
| 71 | #ifdef CONFIG_ACPI | 
|---|
| 72 | #ifdef CONFIG_X86_IO_APIC | 
|---|
| 73 |  | 
|---|
| 74 | static int __init nvidia_hpet_check(struct acpi_table_header *) | 
|---|
| 75 | { | 
|---|
| 76 | return 0; | 
|---|
| 77 | } | 
|---|
| 78 | #endif /* CONFIG_X86_IO_APIC */ | 
|---|
| 79 | #endif /* CONFIG_ACPI */ | 
|---|
| 80 |  | 
|---|
| 81 | static void __init nvidia_bugs(int num, int slot, int func) | 
|---|
| 82 | { | 
|---|
| 83 | #ifdef CONFIG_ACPI | 
|---|
| 84 | #ifdef CONFIG_X86_IO_APIC | 
|---|
| 85 | /* | 
|---|
| 86 | * Only applies to Nvidia root ports (bus 0) and not to | 
|---|
| 87 | * Nvidia graphics cards with PCI ports on secondary buses. | 
|---|
| 88 | */ | 
|---|
| 89 | if (num) | 
|---|
| 90 | return; | 
|---|
| 91 |  | 
|---|
| 92 | /* | 
|---|
| 93 | * All timer overrides on Nvidia are | 
|---|
| 94 | * wrong unless HPET is enabled. | 
|---|
| 95 | * Unfortunately that's not true on many Asus boards. | 
|---|
| 96 | * We don't know yet how to detect this automatically, but | 
|---|
| 97 | * at least allow a command line override. | 
|---|
| 98 | */ | 
|---|
| 99 | if (acpi_use_timer_override) | 
|---|
| 100 | return; | 
|---|
| 101 |  | 
|---|
| 102 | if (acpi_table_parse(ACPI_SIG_HPET, handler: nvidia_hpet_check)) { | 
|---|
| 103 | acpi_skip_timer_override = 1; | 
|---|
| 104 | printk(KERN_INFO "Nvidia board " | 
|---|
| 105 | "detected. Ignoring ACPI " | 
|---|
| 106 | "timer override.\n"); | 
|---|
| 107 | printk(KERN_INFO "If you got timer trouble " | 
|---|
| 108 | "try acpi_use_timer_override\n"); | 
|---|
| 109 | } | 
|---|
| 110 | #endif | 
|---|
| 111 | #endif | 
|---|
| 112 | /* RED-PEN skip them on mptables too? */ | 
|---|
| 113 |  | 
|---|
| 114 | } | 
|---|
| 115 |  | 
|---|
| 116 | #if defined(CONFIG_ACPI) && defined(CONFIG_X86_IO_APIC) | 
|---|
| 117 | static u32 __init ati_ixp4x0_rev(int num, int slot, int func) | 
|---|
| 118 | { | 
|---|
| 119 | u32 d; | 
|---|
| 120 | u8  b; | 
|---|
| 121 |  | 
|---|
| 122 | b = read_pci_config_byte(bus: num, slot, func, offset: 0xac); | 
|---|
| 123 | b &= ~(1<<5); | 
|---|
| 124 | write_pci_config_byte(bus: num, slot, func, offset: 0xac, val: b); | 
|---|
| 125 |  | 
|---|
| 126 | d = read_pci_config(bus: num, slot, func, offset: 0x70); | 
|---|
| 127 | d |= 1<<8; | 
|---|
| 128 | write_pci_config(bus: num, slot, func, offset: 0x70, val: d); | 
|---|
| 129 |  | 
|---|
| 130 | d = read_pci_config(bus: num, slot, func, offset: 0x8); | 
|---|
| 131 | d &= 0xff; | 
|---|
| 132 | return d; | 
|---|
| 133 | } | 
|---|
| 134 |  | 
|---|
| 135 | static void __init ati_bugs(int num, int slot, int func) | 
|---|
| 136 | { | 
|---|
| 137 | u32 d; | 
|---|
| 138 | u8  b; | 
|---|
| 139 |  | 
|---|
| 140 | if (acpi_use_timer_override) | 
|---|
| 141 | return; | 
|---|
| 142 |  | 
|---|
| 143 | d = ati_ixp4x0_rev(num, slot, func); | 
|---|
| 144 | if (d  < 0x82) | 
|---|
| 145 | acpi_skip_timer_override = 1; | 
|---|
| 146 | else { | 
|---|
| 147 | /* check for IRQ0 interrupt swap */ | 
|---|
| 148 | outb(value: 0x72, port: 0xcd6); b = inb(port: 0xcd7); | 
|---|
| 149 | if (!(b & 0x2)) | 
|---|
| 150 | acpi_skip_timer_override = 1; | 
|---|
| 151 | } | 
|---|
| 152 |  | 
|---|
| 153 | if (acpi_skip_timer_override) { | 
|---|
| 154 | printk(KERN_INFO "SB4X0 revision 0x%x\n", d); | 
|---|
| 155 | printk(KERN_INFO "Ignoring ACPI timer override.\n"); | 
|---|
| 156 | printk(KERN_INFO "If you got timer trouble " | 
|---|
| 157 | "try acpi_use_timer_override\n"); | 
|---|
| 158 | } | 
|---|
| 159 | } | 
|---|
| 160 |  | 
|---|
| 161 | static u32 __init ati_sbx00_rev(int num, int slot, int func) | 
|---|
| 162 | { | 
|---|
| 163 | u32 d; | 
|---|
| 164 |  | 
|---|
| 165 | d = read_pci_config(bus: num, slot, func, offset: 0x8); | 
|---|
| 166 | d &= 0xff; | 
|---|
| 167 |  | 
|---|
| 168 | return d; | 
|---|
| 169 | } | 
|---|
| 170 |  | 
|---|
| 171 | static void __init ati_bugs_contd(int num, int slot, int func) | 
|---|
| 172 | { | 
|---|
| 173 | u32 d, rev; | 
|---|
| 174 |  | 
|---|
| 175 | rev = ati_sbx00_rev(num, slot, func); | 
|---|
| 176 | if (rev >= 0x40) | 
|---|
| 177 | acpi_fix_pin2_polarity = 1; | 
|---|
| 178 |  | 
|---|
| 179 | /* | 
|---|
| 180 | * SB600: revisions 0x11, 0x12, 0x13, 0x14, ... | 
|---|
| 181 | * SB700: revisions 0x39, 0x3a, ... | 
|---|
| 182 | * SB800: revisions 0x40, 0x41, ... | 
|---|
| 183 | */ | 
|---|
| 184 | if (rev >= 0x39) | 
|---|
| 185 | return; | 
|---|
| 186 |  | 
|---|
| 187 | if (acpi_use_timer_override) | 
|---|
| 188 | return; | 
|---|
| 189 |  | 
|---|
| 190 | /* check for IRQ0 interrupt swap */ | 
|---|
| 191 | d = read_pci_config(bus: num, slot, func, offset: 0x64); | 
|---|
| 192 | if (!(d & (1<<14))) | 
|---|
| 193 | acpi_skip_timer_override = 1; | 
|---|
| 194 |  | 
|---|
| 195 | if (acpi_skip_timer_override) { | 
|---|
| 196 | printk(KERN_INFO "SB600 revision 0x%x\n", rev); | 
|---|
| 197 | printk(KERN_INFO "Ignoring ACPI timer override.\n"); | 
|---|
| 198 | printk(KERN_INFO "If you got timer trouble " | 
|---|
| 199 | "try acpi_use_timer_override\n"); | 
|---|
| 200 | } | 
|---|
| 201 | } | 
|---|
| 202 | #else | 
|---|
| 203 | static void __init ati_bugs(int num, int slot, int func) | 
|---|
| 204 | { | 
|---|
| 205 | } | 
|---|
| 206 |  | 
|---|
| 207 | static void __init ati_bugs_contd(int num, int slot, int func) | 
|---|
| 208 | { | 
|---|
| 209 | } | 
|---|
| 210 | #endif | 
|---|
| 211 |  | 
|---|
| 212 | static void __init intel_remapping_check(int num, int slot, int func) | 
|---|
| 213 | { | 
|---|
| 214 | u8 revision; | 
|---|
| 215 | u16 device; | 
|---|
| 216 |  | 
|---|
| 217 | device = read_pci_config_16(bus: num, slot, func, PCI_DEVICE_ID); | 
|---|
| 218 | revision = read_pci_config_byte(bus: num, slot, func, PCI_REVISION_ID); | 
|---|
| 219 |  | 
|---|
| 220 | /* | 
|---|
| 221 | * Revision <= 13 of all triggering devices id in this quirk | 
|---|
| 222 | * have a problem draining interrupts when irq remapping is | 
|---|
| 223 | * enabled, and should be flagged as broken. Additionally | 
|---|
| 224 | * revision 0x22 of device id 0x3405 has this problem. | 
|---|
| 225 | */ | 
|---|
| 226 | if (revision <= 0x13) | 
|---|
| 227 | set_irq_remapping_broken(); | 
|---|
| 228 | else if (device == 0x3405 && revision == 0x22) | 
|---|
| 229 | set_irq_remapping_broken(); | 
|---|
| 230 | } | 
|---|
| 231 |  | 
|---|
| 232 | /* | 
|---|
| 233 | * Systems with Intel graphics controllers set aside memory exclusively | 
|---|
| 234 | * for gfx driver use.  This memory is not marked in the E820 as reserved | 
|---|
| 235 | * or as RAM, and so is subject to overlap from E820 manipulation later | 
|---|
| 236 | * in the boot process.  On some systems, MMIO space is allocated on top, | 
|---|
| 237 | * despite the efforts of the "RAM buffer" approach, which simply rounds | 
|---|
| 238 | * memory boundaries up to 64M to try to catch space that may decode | 
|---|
| 239 | * as RAM and so is not suitable for MMIO. | 
|---|
| 240 | */ | 
|---|
| 241 |  | 
|---|
| 242 | #define KB(x)	((x) * 1024UL) | 
|---|
| 243 | #define MB(x)	(KB (KB (x))) | 
|---|
| 244 |  | 
|---|
| 245 | static resource_size_t __init i830_tseg_size(void) | 
|---|
| 246 | { | 
|---|
| 247 | u8 esmramc = read_pci_config_byte(bus: 0, slot: 0, func: 0, I830_ESMRAMC); | 
|---|
| 248 |  | 
|---|
| 249 | if (!(esmramc & TSEG_ENABLE)) | 
|---|
| 250 | return 0; | 
|---|
| 251 |  | 
|---|
| 252 | if (esmramc & I830_TSEG_SIZE_1M) | 
|---|
| 253 | return MB(1); | 
|---|
| 254 | else | 
|---|
| 255 | return KB(512); | 
|---|
| 256 | } | 
|---|
| 257 |  | 
|---|
| 258 | static resource_size_t __init i845_tseg_size(void) | 
|---|
| 259 | { | 
|---|
| 260 | u8 esmramc = read_pci_config_byte(bus: 0, slot: 0, func: 0, I845_ESMRAMC); | 
|---|
| 261 | u8 tseg_size = esmramc & I845_TSEG_SIZE_MASK; | 
|---|
| 262 |  | 
|---|
| 263 | if (!(esmramc & TSEG_ENABLE)) | 
|---|
| 264 | return 0; | 
|---|
| 265 |  | 
|---|
| 266 | switch (tseg_size) { | 
|---|
| 267 | case I845_TSEG_SIZE_512K:	return KB(512); | 
|---|
| 268 | case I845_TSEG_SIZE_1M:		return MB(1); | 
|---|
| 269 | default: | 
|---|
| 270 | WARN(1, "Unknown ESMRAMC value: %x!\n", esmramc); | 
|---|
| 271 | } | 
|---|
| 272 | return 0; | 
|---|
| 273 | } | 
|---|
| 274 |  | 
|---|
| 275 | static resource_size_t __init i85x_tseg_size(void) | 
|---|
| 276 | { | 
|---|
| 277 | u8 esmramc = read_pci_config_byte(bus: 0, slot: 0, func: 0, I85X_ESMRAMC); | 
|---|
| 278 |  | 
|---|
| 279 | if (!(esmramc & TSEG_ENABLE)) | 
|---|
| 280 | return 0; | 
|---|
| 281 |  | 
|---|
| 282 | return MB(1); | 
|---|
| 283 | } | 
|---|
| 284 |  | 
|---|
| 285 | static resource_size_t __init i830_mem_size(void) | 
|---|
| 286 | { | 
|---|
| 287 | return read_pci_config_byte(bus: 0, slot: 0, func: 0, I830_DRB3) * MB(32); | 
|---|
| 288 | } | 
|---|
| 289 |  | 
|---|
| 290 | static resource_size_t __init i85x_mem_size(void) | 
|---|
| 291 | { | 
|---|
| 292 | return read_pci_config_byte(bus: 0, slot: 0, func: 1, I85X_DRB3) * MB(32); | 
|---|
| 293 | } | 
|---|
| 294 |  | 
|---|
| 295 | /* | 
|---|
| 296 | * On 830/845/85x the stolen memory base isn't available in any | 
|---|
| 297 | * register. We need to calculate it as TOM-TSEG_SIZE-stolen_size. | 
|---|
| 298 | */ | 
|---|
| 299 | static resource_size_t __init i830_stolen_base(int num, int slot, int func, | 
|---|
| 300 | resource_size_t stolen_size) | 
|---|
| 301 | { | 
|---|
| 302 | return i830_mem_size() - i830_tseg_size() - stolen_size; | 
|---|
| 303 | } | 
|---|
| 304 |  | 
|---|
| 305 | static resource_size_t __init i845_stolen_base(int num, int slot, int func, | 
|---|
| 306 | resource_size_t stolen_size) | 
|---|
| 307 | { | 
|---|
| 308 | return i830_mem_size() - i845_tseg_size() - stolen_size; | 
|---|
| 309 | } | 
|---|
| 310 |  | 
|---|
| 311 | static resource_size_t __init i85x_stolen_base(int num, int slot, int func, | 
|---|
| 312 | resource_size_t stolen_size) | 
|---|
| 313 | { | 
|---|
| 314 | return i85x_mem_size() - i85x_tseg_size() - stolen_size; | 
|---|
| 315 | } | 
|---|
| 316 |  | 
|---|
| 317 | static resource_size_t __init i865_stolen_base(int num, int slot, int func, | 
|---|
| 318 | resource_size_t stolen_size) | 
|---|
| 319 | { | 
|---|
| 320 | u16 toud = 0; | 
|---|
| 321 |  | 
|---|
| 322 | toud = read_pci_config_16(bus: 0, slot: 0, func: 0, I865_TOUD); | 
|---|
| 323 |  | 
|---|
| 324 | return toud * KB(64) + i845_tseg_size(); | 
|---|
| 325 | } | 
|---|
| 326 |  | 
|---|
| 327 | static resource_size_t __init gen3_stolen_base(int num, int slot, int func, | 
|---|
| 328 | resource_size_t stolen_size) | 
|---|
| 329 | { | 
|---|
| 330 | u32 bsm; | 
|---|
| 331 |  | 
|---|
| 332 | /* Almost universally we can find the Graphics Base of Stolen Memory | 
|---|
| 333 | * at register BSM (0x5c) in the igfx configuration space. On a few | 
|---|
| 334 | * (desktop) machines this is also mirrored in the bridge device at | 
|---|
| 335 | * different locations, or in the MCHBAR. | 
|---|
| 336 | */ | 
|---|
| 337 | bsm = read_pci_config(bus: num, slot, func, INTEL_BSM); | 
|---|
| 338 |  | 
|---|
| 339 | return bsm & INTEL_BSM_MASK; | 
|---|
| 340 | } | 
|---|
| 341 |  | 
|---|
| 342 | static resource_size_t __init gen11_stolen_base(int num, int slot, int func, | 
|---|
| 343 | resource_size_t stolen_size) | 
|---|
| 344 | { | 
|---|
| 345 | u64 bsm; | 
|---|
| 346 |  | 
|---|
| 347 | bsm = read_pci_config(bus: num, slot, func, INTEL_GEN11_BSM_DW0); | 
|---|
| 348 | bsm &= INTEL_BSM_MASK; | 
|---|
| 349 | bsm |= (u64)read_pci_config(bus: num, slot, func, INTEL_GEN11_BSM_DW1) << 32; | 
|---|
| 350 |  | 
|---|
| 351 | return bsm; | 
|---|
| 352 | } | 
|---|
| 353 |  | 
|---|
| 354 | static resource_size_t __init i830_stolen_size(int num, int slot, int func) | 
|---|
| 355 | { | 
|---|
| 356 | u16 gmch_ctrl; | 
|---|
| 357 | u16 gms; | 
|---|
| 358 |  | 
|---|
| 359 | gmch_ctrl = read_pci_config_16(bus: 0, slot: 0, func: 0, I830_GMCH_CTRL); | 
|---|
| 360 | gms = gmch_ctrl & I830_GMCH_GMS_MASK; | 
|---|
| 361 |  | 
|---|
| 362 | switch (gms) { | 
|---|
| 363 | case I830_GMCH_GMS_STOLEN_512:	return KB(512); | 
|---|
| 364 | case I830_GMCH_GMS_STOLEN_1024:	return MB(1); | 
|---|
| 365 | case I830_GMCH_GMS_STOLEN_8192:	return MB(8); | 
|---|
| 366 | /* local memory isn't part of the normal address space */ | 
|---|
| 367 | case I830_GMCH_GMS_LOCAL:	return 0; | 
|---|
| 368 | default: | 
|---|
| 369 | WARN(1, "Unknown GMCH_CTRL value: %x!\n", gmch_ctrl); | 
|---|
| 370 | } | 
|---|
| 371 |  | 
|---|
| 372 | return 0; | 
|---|
| 373 | } | 
|---|
| 374 |  | 
|---|
| 375 | static resource_size_t __init gen3_stolen_size(int num, int slot, int func) | 
|---|
| 376 | { | 
|---|
| 377 | u16 gmch_ctrl; | 
|---|
| 378 | u16 gms; | 
|---|
| 379 |  | 
|---|
| 380 | gmch_ctrl = read_pci_config_16(bus: 0, slot: 0, func: 0, I830_GMCH_CTRL); | 
|---|
| 381 | gms = gmch_ctrl & I855_GMCH_GMS_MASK; | 
|---|
| 382 |  | 
|---|
| 383 | switch (gms) { | 
|---|
| 384 | case I855_GMCH_GMS_STOLEN_1M:	return MB(1); | 
|---|
| 385 | case I855_GMCH_GMS_STOLEN_4M:	return MB(4); | 
|---|
| 386 | case I855_GMCH_GMS_STOLEN_8M:	return MB(8); | 
|---|
| 387 | case I855_GMCH_GMS_STOLEN_16M:	return MB(16); | 
|---|
| 388 | case I855_GMCH_GMS_STOLEN_32M:	return MB(32); | 
|---|
| 389 | case I915_GMCH_GMS_STOLEN_48M:	return MB(48); | 
|---|
| 390 | case I915_GMCH_GMS_STOLEN_64M:	return MB(64); | 
|---|
| 391 | case G33_GMCH_GMS_STOLEN_128M:	return MB(128); | 
|---|
| 392 | case G33_GMCH_GMS_STOLEN_256M:	return MB(256); | 
|---|
| 393 | case INTEL_GMCH_GMS_STOLEN_96M:	return MB(96); | 
|---|
| 394 | case INTEL_GMCH_GMS_STOLEN_160M:return MB(160); | 
|---|
| 395 | case INTEL_GMCH_GMS_STOLEN_224M:return MB(224); | 
|---|
| 396 | case INTEL_GMCH_GMS_STOLEN_352M:return MB(352); | 
|---|
| 397 | default: | 
|---|
| 398 | WARN(1, "Unknown GMCH_CTRL value: %x!\n", gmch_ctrl); | 
|---|
| 399 | } | 
|---|
| 400 |  | 
|---|
| 401 | return 0; | 
|---|
| 402 | } | 
|---|
| 403 |  | 
|---|
| 404 | static resource_size_t __init gen6_stolen_size(int num, int slot, int func) | 
|---|
| 405 | { | 
|---|
| 406 | u16 gmch_ctrl; | 
|---|
| 407 | u16 gms; | 
|---|
| 408 |  | 
|---|
| 409 | gmch_ctrl = read_pci_config_16(bus: num, slot, func, SNB_GMCH_CTRL); | 
|---|
| 410 | gms = (gmch_ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK; | 
|---|
| 411 |  | 
|---|
| 412 | return gms * MB(32); | 
|---|
| 413 | } | 
|---|
| 414 |  | 
|---|
| 415 | static resource_size_t __init gen8_stolen_size(int num, int slot, int func) | 
|---|
| 416 | { | 
|---|
| 417 | u16 gmch_ctrl; | 
|---|
| 418 | u16 gms; | 
|---|
| 419 |  | 
|---|
| 420 | gmch_ctrl = read_pci_config_16(bus: num, slot, func, SNB_GMCH_CTRL); | 
|---|
| 421 | gms = (gmch_ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK; | 
|---|
| 422 |  | 
|---|
| 423 | return gms * MB(32); | 
|---|
| 424 | } | 
|---|
| 425 |  | 
|---|
| 426 | static resource_size_t __init chv_stolen_size(int num, int slot, int func) | 
|---|
| 427 | { | 
|---|
| 428 | u16 gmch_ctrl; | 
|---|
| 429 | u16 gms; | 
|---|
| 430 |  | 
|---|
| 431 | gmch_ctrl = read_pci_config_16(bus: num, slot, func, SNB_GMCH_CTRL); | 
|---|
| 432 | gms = (gmch_ctrl >> SNB_GMCH_GMS_SHIFT) & SNB_GMCH_GMS_MASK; | 
|---|
| 433 |  | 
|---|
| 434 | /* | 
|---|
| 435 | * 0x0  to 0x10: 32MB increments starting at 0MB | 
|---|
| 436 | * 0x11 to 0x16: 4MB increments starting at 8MB | 
|---|
| 437 | * 0x17 to 0x1d: 4MB increments start at 36MB | 
|---|
| 438 | */ | 
|---|
| 439 | if (gms < 0x11) | 
|---|
| 440 | return gms * MB(32); | 
|---|
| 441 | else if (gms < 0x17) | 
|---|
| 442 | return (gms - 0x11) * MB(4) + MB(8); | 
|---|
| 443 | else | 
|---|
| 444 | return (gms - 0x17) * MB(4) + MB(36); | 
|---|
| 445 | } | 
|---|
| 446 |  | 
|---|
| 447 | static resource_size_t __init gen9_stolen_size(int num, int slot, int func) | 
|---|
| 448 | { | 
|---|
| 449 | u16 gmch_ctrl; | 
|---|
| 450 | u16 gms; | 
|---|
| 451 |  | 
|---|
| 452 | gmch_ctrl = read_pci_config_16(bus: num, slot, func, SNB_GMCH_CTRL); | 
|---|
| 453 | gms = (gmch_ctrl >> BDW_GMCH_GMS_SHIFT) & BDW_GMCH_GMS_MASK; | 
|---|
| 454 |  | 
|---|
| 455 | /* 0x0  to 0xef: 32MB increments starting at 0MB */ | 
|---|
| 456 | /* 0xf0 to 0xfe: 4MB increments starting at 4MB */ | 
|---|
| 457 | if (gms < 0xf0) | 
|---|
| 458 | return gms * MB(32); | 
|---|
| 459 | else | 
|---|
| 460 | return (gms - 0xf0) * MB(4) + MB(4); | 
|---|
| 461 | } | 
|---|
| 462 |  | 
|---|
| 463 | struct intel_early_ops { | 
|---|
| 464 | resource_size_t (*stolen_size)(int num, int slot, int func); | 
|---|
| 465 | resource_size_t (*stolen_base)(int num, int slot, int func, | 
|---|
| 466 | resource_size_t size); | 
|---|
| 467 | }; | 
|---|
| 468 |  | 
|---|
| 469 | static const struct intel_early_ops i830_early_ops __initconst = { | 
|---|
| 470 | .stolen_base = i830_stolen_base, | 
|---|
| 471 | .stolen_size = i830_stolen_size, | 
|---|
| 472 | }; | 
|---|
| 473 |  | 
|---|
| 474 | static const struct intel_early_ops i845_early_ops __initconst = { | 
|---|
| 475 | .stolen_base = i845_stolen_base, | 
|---|
| 476 | .stolen_size = i830_stolen_size, | 
|---|
| 477 | }; | 
|---|
| 478 |  | 
|---|
| 479 | static const struct intel_early_ops i85x_early_ops __initconst = { | 
|---|
| 480 | .stolen_base = i85x_stolen_base, | 
|---|
| 481 | .stolen_size = gen3_stolen_size, | 
|---|
| 482 | }; | 
|---|
| 483 |  | 
|---|
| 484 | static const struct intel_early_ops i865_early_ops __initconst = { | 
|---|
| 485 | .stolen_base = i865_stolen_base, | 
|---|
| 486 | .stolen_size = gen3_stolen_size, | 
|---|
| 487 | }; | 
|---|
| 488 |  | 
|---|
| 489 | static const struct intel_early_ops gen3_early_ops __initconst = { | 
|---|
| 490 | .stolen_base = gen3_stolen_base, | 
|---|
| 491 | .stolen_size = gen3_stolen_size, | 
|---|
| 492 | }; | 
|---|
| 493 |  | 
|---|
| 494 | static const struct intel_early_ops gen6_early_ops __initconst = { | 
|---|
| 495 | .stolen_base = gen3_stolen_base, | 
|---|
| 496 | .stolen_size = gen6_stolen_size, | 
|---|
| 497 | }; | 
|---|
| 498 |  | 
|---|
| 499 | static const struct intel_early_ops gen8_early_ops __initconst = { | 
|---|
| 500 | .stolen_base = gen3_stolen_base, | 
|---|
| 501 | .stolen_size = gen8_stolen_size, | 
|---|
| 502 | }; | 
|---|
| 503 |  | 
|---|
| 504 | static const struct intel_early_ops gen9_early_ops __initconst = { | 
|---|
| 505 | .stolen_base = gen3_stolen_base, | 
|---|
| 506 | .stolen_size = gen9_stolen_size, | 
|---|
| 507 | }; | 
|---|
| 508 |  | 
|---|
| 509 | static const struct intel_early_ops chv_early_ops __initconst = { | 
|---|
| 510 | .stolen_base = gen3_stolen_base, | 
|---|
| 511 | .stolen_size = chv_stolen_size, | 
|---|
| 512 | }; | 
|---|
| 513 |  | 
|---|
| 514 | static const struct intel_early_ops gen11_early_ops __initconst = { | 
|---|
| 515 | .stolen_base = gen11_stolen_base, | 
|---|
| 516 | .stolen_size = gen9_stolen_size, | 
|---|
| 517 | }; | 
|---|
| 518 |  | 
|---|
| 519 | /* Intel integrated GPUs for which we need to reserve "stolen memory" */ | 
|---|
| 520 | static const struct pci_device_id intel_early_ids[] __initconst = { | 
|---|
| 521 | INTEL_I830_IDS(INTEL_VGA_DEVICE, &i830_early_ops), | 
|---|
| 522 | INTEL_I845G_IDS(INTEL_VGA_DEVICE, &i845_early_ops), | 
|---|
| 523 | INTEL_I85X_IDS(INTEL_VGA_DEVICE, &i85x_early_ops), | 
|---|
| 524 | INTEL_I865G_IDS(INTEL_VGA_DEVICE, &i865_early_ops), | 
|---|
| 525 | INTEL_I915G_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 526 | INTEL_I915GM_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 527 | INTEL_I945G_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 528 | INTEL_I945GM_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 529 | INTEL_VLV_IDS(INTEL_VGA_DEVICE, &gen6_early_ops), | 
|---|
| 530 | INTEL_PNV_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 531 | INTEL_I965G_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 532 | INTEL_G33_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 533 | INTEL_I965GM_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 534 | INTEL_GM45_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 535 | INTEL_G45_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 536 | INTEL_ILK_IDS(INTEL_VGA_DEVICE, &gen3_early_ops), | 
|---|
| 537 | INTEL_SNB_IDS(INTEL_VGA_DEVICE, &gen6_early_ops), | 
|---|
| 538 | INTEL_IVB_IDS(INTEL_VGA_DEVICE, &gen6_early_ops), | 
|---|
| 539 | INTEL_HSW_IDS(INTEL_VGA_DEVICE, &gen6_early_ops), | 
|---|
| 540 | INTEL_BDW_IDS(INTEL_VGA_DEVICE, &gen8_early_ops), | 
|---|
| 541 | INTEL_CHV_IDS(INTEL_VGA_DEVICE, &chv_early_ops), | 
|---|
| 542 | INTEL_SKL_IDS(INTEL_VGA_DEVICE, &gen9_early_ops), | 
|---|
| 543 | INTEL_BXT_IDS(INTEL_VGA_DEVICE, &gen9_early_ops), | 
|---|
| 544 | INTEL_KBL_IDS(INTEL_VGA_DEVICE, &gen9_early_ops), | 
|---|
| 545 | INTEL_CFL_IDS(INTEL_VGA_DEVICE, &gen9_early_ops), | 
|---|
| 546 | INTEL_WHL_IDS(INTEL_VGA_DEVICE, &gen9_early_ops), | 
|---|
| 547 | INTEL_CML_IDS(INTEL_VGA_DEVICE, &gen9_early_ops), | 
|---|
| 548 | INTEL_GLK_IDS(INTEL_VGA_DEVICE, &gen9_early_ops), | 
|---|
| 549 | INTEL_CNL_IDS(INTEL_VGA_DEVICE, &gen9_early_ops), | 
|---|
| 550 | INTEL_ICL_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 551 | INTEL_EHL_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 552 | INTEL_JSL_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 553 | INTEL_TGL_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 554 | INTEL_RKL_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 555 | INTEL_ADLS_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 556 | INTEL_ADLP_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 557 | INTEL_ADLN_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 558 | INTEL_RPLS_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 559 | INTEL_RPLU_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 560 | INTEL_RPLP_IDS(INTEL_VGA_DEVICE, &gen11_early_ops), | 
|---|
| 561 | }; | 
|---|
| 562 |  | 
|---|
| 563 | struct resource intel_graphics_stolen_res __ro_after_init = DEFINE_RES_MEM(0, 0); | 
|---|
| 564 | EXPORT_SYMBOL(intel_graphics_stolen_res); | 
|---|
| 565 |  | 
|---|
| 566 | static void __init | 
|---|
| 567 | intel_graphics_stolen(int num, int slot, int func, | 
|---|
| 568 | const struct intel_early_ops *early_ops) | 
|---|
| 569 | { | 
|---|
| 570 | resource_size_t base, size; | 
|---|
| 571 | resource_size_t end; | 
|---|
| 572 |  | 
|---|
| 573 | size = early_ops->stolen_size(num, slot, func); | 
|---|
| 574 | base = early_ops->stolen_base(num, slot, func, size); | 
|---|
| 575 |  | 
|---|
| 576 | if (!size || !base) | 
|---|
| 577 | return; | 
|---|
| 578 |  | 
|---|
| 579 | end = base + size - 1; | 
|---|
| 580 |  | 
|---|
| 581 | intel_graphics_stolen_res.start = base; | 
|---|
| 582 | intel_graphics_stolen_res.end = end; | 
|---|
| 583 |  | 
|---|
| 584 | printk(KERN_INFO "Reserving Intel graphics memory at %pR\n", | 
|---|
| 585 | &intel_graphics_stolen_res); | 
|---|
| 586 |  | 
|---|
| 587 | /* Mark this space as reserved */ | 
|---|
| 588 | e820__range_add(start: base, size, type: E820_TYPE_RESERVED); | 
|---|
| 589 | e820__update_table(table: e820_table); | 
|---|
| 590 | } | 
|---|
| 591 |  | 
|---|
| 592 | static void __init intel_graphics_quirks(int num, int slot, int func) | 
|---|
| 593 | { | 
|---|
| 594 | const struct intel_early_ops *early_ops; | 
|---|
| 595 | u16 device; | 
|---|
| 596 | int i; | 
|---|
| 597 |  | 
|---|
| 598 | /* | 
|---|
| 599 | * Reserve "stolen memory" for an integrated GPU.  If we've already | 
|---|
| 600 | * found one, there's nothing to do for other (discrete) GPUs. | 
|---|
| 601 | */ | 
|---|
| 602 | if (resource_size(res: &intel_graphics_stolen_res)) | 
|---|
| 603 | return; | 
|---|
| 604 |  | 
|---|
| 605 | device = read_pci_config_16(bus: num, slot, func, PCI_DEVICE_ID); | 
|---|
| 606 |  | 
|---|
| 607 | for (i = 0; i < ARRAY_SIZE(intel_early_ids); i++) { | 
|---|
| 608 | kernel_ulong_t driver_data = intel_early_ids[i].driver_data; | 
|---|
| 609 |  | 
|---|
| 610 | if (intel_early_ids[i].device != device) | 
|---|
| 611 | continue; | 
|---|
| 612 |  | 
|---|
| 613 | early_ops = (typeof(early_ops))driver_data; | 
|---|
| 614 |  | 
|---|
| 615 | intel_graphics_stolen(num, slot, func, early_ops); | 
|---|
| 616 |  | 
|---|
| 617 | return; | 
|---|
| 618 | } | 
|---|
| 619 | } | 
|---|
| 620 |  | 
|---|
| 621 | static void __init force_disable_hpet(int num, int slot, int func) | 
|---|
| 622 | { | 
|---|
| 623 | #ifdef CONFIG_HPET_TIMER | 
|---|
| 624 | boot_hpet_disable = true; | 
|---|
| 625 | pr_info( "x86/hpet: Will disable the HPET for this platform because it's not reliable\n"); | 
|---|
| 626 | #endif | 
|---|
| 627 | } | 
|---|
| 628 |  | 
|---|
| 629 | #define BCM4331_MMIO_SIZE	16384 | 
|---|
| 630 | #define BCM4331_PM_CAP		0x40 | 
|---|
| 631 | #define bcma_aread32(reg)	ioread32(mmio + 1 * BCMA_CORE_SIZE + reg) | 
|---|
| 632 | #define bcma_awrite32(reg, val)	iowrite32(val, mmio + 1 * BCMA_CORE_SIZE + reg) | 
|---|
| 633 |  | 
|---|
| 634 | static void __init apple_airport_reset(int bus, int slot, int func) | 
|---|
| 635 | { | 
|---|
| 636 | void __iomem *mmio; | 
|---|
| 637 | u16 pmcsr; | 
|---|
| 638 | u64 addr; | 
|---|
| 639 | int i; | 
|---|
| 640 |  | 
|---|
| 641 | if (!x86_apple_machine) | 
|---|
| 642 | return; | 
|---|
| 643 |  | 
|---|
| 644 | /* Card may have been put into PCI_D3hot by grub quirk */ | 
|---|
| 645 | pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL); | 
|---|
| 646 |  | 
|---|
| 647 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) { | 
|---|
| 648 | pmcsr &= ~PCI_PM_CTRL_STATE_MASK; | 
|---|
| 649 | write_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL, val: pmcsr); | 
|---|
| 650 | mdelay(10); | 
|---|
| 651 |  | 
|---|
| 652 | pmcsr = read_pci_config_16(bus, slot, func, BCM4331_PM_CAP + PCI_PM_CTRL); | 
|---|
| 653 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) != PCI_D0) { | 
|---|
| 654 | pr_err( "pci 0000:%02x:%02x.%d: Cannot power up Apple AirPort card\n", | 
|---|
| 655 | bus, slot, func); | 
|---|
| 656 | return; | 
|---|
| 657 | } | 
|---|
| 658 | } | 
|---|
| 659 |  | 
|---|
| 660 | addr  =      read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0); | 
|---|
| 661 | addr |= (u64)read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_1) << 32; | 
|---|
| 662 | addr &= PCI_BASE_ADDRESS_MEM_MASK; | 
|---|
| 663 |  | 
|---|
| 664 | mmio = early_ioremap(phys_addr: addr, BCM4331_MMIO_SIZE); | 
|---|
| 665 | if (!mmio) { | 
|---|
| 666 | pr_err( "pci 0000:%02x:%02x.%d: Cannot iomap Apple AirPort card\n", | 
|---|
| 667 | bus, slot, func); | 
|---|
| 668 | return; | 
|---|
| 669 | } | 
|---|
| 670 |  | 
|---|
| 671 | pr_info( "Resetting Apple AirPort card (left enabled by EFI)\n"); | 
|---|
| 672 |  | 
|---|
| 673 | for (i = 0; bcma_aread32(BCMA_RESET_ST) && i < 30; i++) | 
|---|
| 674 | udelay(usec: 10); | 
|---|
| 675 |  | 
|---|
| 676 | bcma_awrite32(BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); | 
|---|
| 677 | bcma_aread32(BCMA_RESET_CTL); | 
|---|
| 678 | udelay(usec: 1); | 
|---|
| 679 |  | 
|---|
| 680 | bcma_awrite32(BCMA_RESET_CTL, 0); | 
|---|
| 681 | bcma_aread32(BCMA_RESET_CTL); | 
|---|
| 682 | udelay(usec: 10); | 
|---|
| 683 |  | 
|---|
| 684 | early_iounmap(addr: mmio, BCM4331_MMIO_SIZE); | 
|---|
| 685 | } | 
|---|
| 686 |  | 
|---|
| 687 | #define QFLAG_APPLY_ONCE 	0x1 | 
|---|
| 688 | #define QFLAG_APPLIED		0x2 | 
|---|
| 689 | #define QFLAG_DONE		(QFLAG_APPLY_ONCE|QFLAG_APPLIED) | 
|---|
| 690 | struct chipset { | 
|---|
| 691 | u32 vendor; | 
|---|
| 692 | u32 device; | 
|---|
| 693 | u32 class; | 
|---|
| 694 | u32 class_mask; | 
|---|
| 695 | u32 flags; | 
|---|
| 696 | void (*f)(int num, int slot, int func); | 
|---|
| 697 | }; | 
|---|
| 698 |  | 
|---|
| 699 | static struct chipset early_qrk[] __initdata = { | 
|---|
| 700 | { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, | 
|---|
| 701 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, nvidia_bugs }, | 
|---|
| 702 | { PCI_VENDOR_ID_VIA, PCI_ANY_ID, | 
|---|
| 703 | PCI_CLASS_BRIDGE_PCI, PCI_ANY_ID, QFLAG_APPLY_ONCE, .class_mask: via_bugs }, | 
|---|
| 704 | { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB, | 
|---|
| 705 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, fix_hypertransport_config }, | 
|---|
| 706 | { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS, | 
|---|
| 707 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, .class: 0, .class_mask: ati_bugs }, | 
|---|
| 708 | { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS, | 
|---|
| 709 | PCI_CLASS_SERIAL_SMBUS, PCI_ANY_ID, 0, ati_bugs_contd }, | 
|---|
| 710 | { PCI_VENDOR_ID_INTEL, 0x3403, PCI_CLASS_BRIDGE_HOST, | 
|---|
| 711 | PCI_BASE_CLASS_BRIDGE, .class: 0, .class_mask: intel_remapping_check }, | 
|---|
| 712 | { PCI_VENDOR_ID_INTEL, 0x3405, PCI_CLASS_BRIDGE_HOST, | 
|---|
| 713 | PCI_BASE_CLASS_BRIDGE, 0, intel_remapping_check }, | 
|---|
| 714 | { PCI_VENDOR_ID_INTEL, 0x3406, PCI_CLASS_BRIDGE_HOST, | 
|---|
| 715 | PCI_BASE_CLASS_BRIDGE, .class: 0, .class_mask: intel_remapping_check }, | 
|---|
| 716 | { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, PCI_ANY_ID, | 
|---|
| 717 | 0, intel_graphics_quirks }, | 
|---|
| 718 | /* | 
|---|
| 719 | * HPET on the current version of the Baytrail platform has accuracy | 
|---|
| 720 | * problems: it will halt in deep idle state - so we disable it. | 
|---|
| 721 | * | 
|---|
| 722 | * More details can be found in section 18.10.1.3 of the datasheet: | 
|---|
| 723 | * | 
|---|
| 724 | *    http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/atom-z8000-datasheet-vol-1.pdf | 
|---|
| 725 | */ | 
|---|
| 726 | { PCI_VENDOR_ID_INTEL, 0x0f00, | 
|---|
| 727 | PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, .class: 0, .class_mask: force_disable_hpet}, | 
|---|
| 728 | { PCI_VENDOR_ID_BROADCOM, 0x4331, | 
|---|
| 729 | PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset}, | 
|---|
| 730 | {} | 
|---|
| 731 | }; | 
|---|
| 732 |  | 
|---|
| 733 | static void __init early_pci_scan_bus(int bus); | 
|---|
| 734 |  | 
|---|
| 735 | /** | 
|---|
| 736 | * check_dev_quirk - apply early quirks to a given PCI device | 
|---|
| 737 | * @num: bus number | 
|---|
| 738 | * @slot: slot number | 
|---|
| 739 | * @func: PCI function | 
|---|
| 740 | * | 
|---|
| 741 | * Check the vendor & device ID against the early quirks table. | 
|---|
| 742 | * | 
|---|
| 743 | * If the device is single function, let early_pci_scan_bus() know so we don't | 
|---|
| 744 | * poke at this device again. | 
|---|
| 745 | */ | 
|---|
| 746 | static int __init check_dev_quirk(int num, int slot, int func) | 
|---|
| 747 | { | 
|---|
| 748 | u16 class; | 
|---|
| 749 | u16 vendor; | 
|---|
| 750 | u16 device; | 
|---|
| 751 | u8 type; | 
|---|
| 752 | u8 sec; | 
|---|
| 753 | int i; | 
|---|
| 754 |  | 
|---|
| 755 | class = read_pci_config_16(bus: num, slot, func, PCI_CLASS_DEVICE); | 
|---|
| 756 |  | 
|---|
| 757 | if (class == 0xffff) | 
|---|
| 758 | return -1; /* no class, treat as single function */ | 
|---|
| 759 |  | 
|---|
| 760 | vendor = read_pci_config_16(bus: num, slot, func, PCI_VENDOR_ID); | 
|---|
| 761 |  | 
|---|
| 762 | device = read_pci_config_16(bus: num, slot, func, PCI_DEVICE_ID); | 
|---|
| 763 |  | 
|---|
| 764 | for (i = 0; early_qrk[i].f != NULL; i++) { | 
|---|
| 765 | if (((early_qrk[i].vendor == PCI_ANY_ID) || | 
|---|
| 766 | (early_qrk[i].vendor == vendor)) && | 
|---|
| 767 | ((early_qrk[i].device == PCI_ANY_ID) || | 
|---|
| 768 | (early_qrk[i].device == device)) && | 
|---|
| 769 | (!((early_qrk[i].class ^ class) & | 
|---|
| 770 | early_qrk[i].class_mask))) { | 
|---|
| 771 | if ((early_qrk[i].flags & | 
|---|
| 772 | QFLAG_DONE) != QFLAG_DONE) | 
|---|
| 773 | early_qrk[i].f(num, slot, func); | 
|---|
| 774 | early_qrk[i].flags |= QFLAG_APPLIED; | 
|---|
| 775 | } | 
|---|
| 776 | } | 
|---|
| 777 |  | 
|---|
| 778 | type = read_pci_config_byte(bus: num, slot, func, | 
|---|
| 779 | PCI_HEADER_TYPE); | 
|---|
| 780 |  | 
|---|
| 781 | if ((type & PCI_HEADER_TYPE_MASK) == PCI_HEADER_TYPE_BRIDGE) { | 
|---|
| 782 | sec = read_pci_config_byte(bus: num, slot, func, PCI_SECONDARY_BUS); | 
|---|
| 783 | if (sec > num) | 
|---|
| 784 | early_pci_scan_bus(bus: sec); | 
|---|
| 785 | } | 
|---|
| 786 |  | 
|---|
| 787 | if (!(type & PCI_HEADER_TYPE_MFD)) | 
|---|
| 788 | return -1; | 
|---|
| 789 |  | 
|---|
| 790 | return 0; | 
|---|
| 791 | } | 
|---|
| 792 |  | 
|---|
| 793 | static void __init early_pci_scan_bus(int bus) | 
|---|
| 794 | { | 
|---|
| 795 | int slot, func; | 
|---|
| 796 |  | 
|---|
| 797 | /* Poor man's PCI discovery */ | 
|---|
| 798 | for (slot = 0; slot < 32; slot++) | 
|---|
| 799 | for (func = 0; func < 8; func++) { | 
|---|
| 800 | /* Only probe function 0 on single fn devices */ | 
|---|
| 801 | if (check_dev_quirk(num: bus, slot, func)) | 
|---|
| 802 | break; | 
|---|
| 803 | } | 
|---|
| 804 | } | 
|---|
| 805 |  | 
|---|
| 806 | void __init early_quirks(void) | 
|---|
| 807 | { | 
|---|
| 808 | if (!early_pci_allowed()) | 
|---|
| 809 | return; | 
|---|
| 810 |  | 
|---|
| 811 | early_pci_scan_bus(bus: 0); | 
|---|
| 812 | } | 
|---|
| 813 |  | 
|---|