162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file contains work-arounds for x86 and x86_64 platform bugs.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#include <linux/dmi.h>
662306a36Sopenharmony_ci#include <linux/pci.h>
762306a36Sopenharmony_ci#include <linux/irq.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <asm/hpet.h>
1062306a36Sopenharmony_ci#include <asm/setup.h>
1162306a36Sopenharmony_ci#include <asm/mce.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#if defined(CONFIG_X86_IO_APIC) && defined(CONFIG_SMP) && defined(CONFIG_PCI)
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cistatic void quirk_intel_irqbalance(struct pci_dev *dev)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	u8 config;
1862306a36Sopenharmony_ci	u16 word;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	/* BIOS may enable hardware IRQ balancing for
2162306a36Sopenharmony_ci	 * E7520/E7320/E7525(revision ID 0x9 and below)
2262306a36Sopenharmony_ci	 * based platforms.
2362306a36Sopenharmony_ci	 * Disable SW irqbalance/affinity on those platforms.
2462306a36Sopenharmony_ci	 */
2562306a36Sopenharmony_ci	if (dev->revision > 0x9)
2662306a36Sopenharmony_ci		return;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	/* enable access to config space*/
2962306a36Sopenharmony_ci	pci_read_config_byte(dev, 0xf4, &config);
3062306a36Sopenharmony_ci	pci_write_config_byte(dev, 0xf4, config|0x2);
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	/*
3362306a36Sopenharmony_ci	 * read xTPR register.  We may not have a pci_dev for device 8
3462306a36Sopenharmony_ci	 * because it might be hidden until the above write.
3562306a36Sopenharmony_ci	 */
3662306a36Sopenharmony_ci	pci_bus_read_config_word(dev->bus, PCI_DEVFN(8, 0), 0x4c, &word);
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (!(word & (1 << 13))) {
3962306a36Sopenharmony_ci		dev_info(&dev->dev, "Intel E7520/7320/7525 detected; "
4062306a36Sopenharmony_ci			"disabling irq balancing and affinity\n");
4162306a36Sopenharmony_ci		noirqdebug_setup("");
4262306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS
4362306a36Sopenharmony_ci		no_irq_affinity = 1;
4462306a36Sopenharmony_ci#endif
4562306a36Sopenharmony_ci	}
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	/* put back the original value for config space*/
4862306a36Sopenharmony_ci	if (!(config & 0x2))
4962306a36Sopenharmony_ci		pci_write_config_byte(dev, 0xf4, config);
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7320_MCH,
5262306a36Sopenharmony_ci			quirk_intel_irqbalance);
5362306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7525_MCH,
5462306a36Sopenharmony_ci			quirk_intel_irqbalance);
5562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH,
5662306a36Sopenharmony_ci			quirk_intel_irqbalance);
5762306a36Sopenharmony_ci#endif
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci#if defined(CONFIG_HPET_TIMER)
6062306a36Sopenharmony_ciunsigned long force_hpet_address;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistatic enum {
6362306a36Sopenharmony_ci	NONE_FORCE_HPET_RESUME,
6462306a36Sopenharmony_ci	OLD_ICH_FORCE_HPET_RESUME,
6562306a36Sopenharmony_ci	ICH_FORCE_HPET_RESUME,
6662306a36Sopenharmony_ci	VT8237_FORCE_HPET_RESUME,
6762306a36Sopenharmony_ci	NVIDIA_FORCE_HPET_RESUME,
6862306a36Sopenharmony_ci	ATI_FORCE_HPET_RESUME,
6962306a36Sopenharmony_ci} force_hpet_resume_type;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic void __iomem *rcba_base;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic void ich_force_hpet_resume(void)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	u32 val;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	if (!force_hpet_address)
7862306a36Sopenharmony_ci		return;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	BUG_ON(rcba_base == NULL);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	/* read the Function Disable register, dword mode only */
8362306a36Sopenharmony_ci	val = readl(rcba_base + 0x3404);
8462306a36Sopenharmony_ci	if (!(val & 0x80)) {
8562306a36Sopenharmony_ci		/* HPET disabled in HPTC. Trying to enable */
8662306a36Sopenharmony_ci		writel(val | 0x80, rcba_base + 0x3404);
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	val = readl(rcba_base + 0x3404);
9062306a36Sopenharmony_ci	if (!(val & 0x80))
9162306a36Sopenharmony_ci		BUG();
9262306a36Sopenharmony_ci	else
9362306a36Sopenharmony_ci		printk(KERN_DEBUG "Force enabled HPET at resume\n");
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic void ich_force_enable_hpet(struct pci_dev *dev)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	u32 val;
9962306a36Sopenharmony_ci	u32 rcba;
10062306a36Sopenharmony_ci	int err = 0;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	if (hpet_address || force_hpet_address)
10362306a36Sopenharmony_ci		return;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	pci_read_config_dword(dev, 0xF0, &rcba);
10662306a36Sopenharmony_ci	rcba &= 0xFFFFC000;
10762306a36Sopenharmony_ci	if (rcba == 0) {
10862306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev, "RCBA disabled; "
10962306a36Sopenharmony_ci			"cannot force enable HPET\n");
11062306a36Sopenharmony_ci		return;
11162306a36Sopenharmony_ci	}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/* use bits 31:14, 16 kB aligned */
11462306a36Sopenharmony_ci	rcba_base = ioremap(rcba, 0x4000);
11562306a36Sopenharmony_ci	if (rcba_base == NULL) {
11662306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev, "ioremap failed; "
11762306a36Sopenharmony_ci			"cannot force enable HPET\n");
11862306a36Sopenharmony_ci		return;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	/* read the Function Disable register, dword mode only */
12262306a36Sopenharmony_ci	val = readl(rcba_base + 0x3404);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (val & 0x80) {
12562306a36Sopenharmony_ci		/* HPET is enabled in HPTC. Just not reported by BIOS */
12662306a36Sopenharmony_ci		val = val & 0x3;
12762306a36Sopenharmony_ci		force_hpet_address = 0xFED00000 | (val << 12);
12862306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
12962306a36Sopenharmony_ci			"0x%lx\n", force_hpet_address);
13062306a36Sopenharmony_ci		iounmap(rcba_base);
13162306a36Sopenharmony_ci		return;
13262306a36Sopenharmony_ci	}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	/* HPET disabled in HPTC. Trying to enable */
13562306a36Sopenharmony_ci	writel(val | 0x80, rcba_base + 0x3404);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	val = readl(rcba_base + 0x3404);
13862306a36Sopenharmony_ci	if (!(val & 0x80)) {
13962306a36Sopenharmony_ci		err = 1;
14062306a36Sopenharmony_ci	} else {
14162306a36Sopenharmony_ci		val = val & 0x3;
14262306a36Sopenharmony_ci		force_hpet_address = 0xFED00000 | (val << 12);
14362306a36Sopenharmony_ci	}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	if (err) {
14662306a36Sopenharmony_ci		force_hpet_address = 0;
14762306a36Sopenharmony_ci		iounmap(rcba_base);
14862306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev,
14962306a36Sopenharmony_ci			"Failed to force enable HPET\n");
15062306a36Sopenharmony_ci	} else {
15162306a36Sopenharmony_ci		force_hpet_resume_type = ICH_FORCE_HPET_RESUME;
15262306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
15362306a36Sopenharmony_ci			"0x%lx\n", force_hpet_address);
15462306a36Sopenharmony_ci	}
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_0,
15862306a36Sopenharmony_ci			 ich_force_enable_hpet);
15962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0,
16062306a36Sopenharmony_ci			 ich_force_enable_hpet);
16162306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1,
16262306a36Sopenharmony_ci			 ich_force_enable_hpet);
16362306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,
16462306a36Sopenharmony_ci			 ich_force_enable_hpet);
16562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,
16662306a36Sopenharmony_ci			 ich_force_enable_hpet);
16762306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,
16862306a36Sopenharmony_ci			 ich_force_enable_hpet);
16962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_1,
17062306a36Sopenharmony_ci			 ich_force_enable_hpet);
17162306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_4,
17262306a36Sopenharmony_ci			 ich_force_enable_hpet);
17362306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_7,
17462306a36Sopenharmony_ci			 ich_force_enable_hpet);
17562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x3a16,	/* ICH10 */
17662306a36Sopenharmony_ci			 ich_force_enable_hpet);
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic struct pci_dev *cached_dev;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic void hpet_print_force_info(void)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	printk(KERN_INFO "HPET not enabled in BIOS. "
18362306a36Sopenharmony_ci	       "You might try hpet=force boot option\n");
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic void old_ich_force_hpet_resume(void)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	u32 val;
18962306a36Sopenharmony_ci	u32 gen_cntl;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	if (!force_hpet_address || !cached_dev)
19262306a36Sopenharmony_ci		return;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	pci_read_config_dword(cached_dev, 0xD0, &gen_cntl);
19562306a36Sopenharmony_ci	gen_cntl &= (~(0x7 << 15));
19662306a36Sopenharmony_ci	gen_cntl |= (0x4 << 15);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	pci_write_config_dword(cached_dev, 0xD0, gen_cntl);
19962306a36Sopenharmony_ci	pci_read_config_dword(cached_dev, 0xD0, &gen_cntl);
20062306a36Sopenharmony_ci	val = gen_cntl >> 15;
20162306a36Sopenharmony_ci	val &= 0x7;
20262306a36Sopenharmony_ci	if (val == 0x4)
20362306a36Sopenharmony_ci		printk(KERN_DEBUG "Force enabled HPET at resume\n");
20462306a36Sopenharmony_ci	else
20562306a36Sopenharmony_ci		BUG();
20662306a36Sopenharmony_ci}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_cistatic void old_ich_force_enable_hpet(struct pci_dev *dev)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	u32 val;
21162306a36Sopenharmony_ci	u32 gen_cntl;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	if (hpet_address || force_hpet_address)
21462306a36Sopenharmony_ci		return;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	pci_read_config_dword(dev, 0xD0, &gen_cntl);
21762306a36Sopenharmony_ci	/*
21862306a36Sopenharmony_ci	 * Bit 17 is HPET enable bit.
21962306a36Sopenharmony_ci	 * Bit 16:15 control the HPET base address.
22062306a36Sopenharmony_ci	 */
22162306a36Sopenharmony_ci	val = gen_cntl >> 15;
22262306a36Sopenharmony_ci	val &= 0x7;
22362306a36Sopenharmony_ci	if (val & 0x4) {
22462306a36Sopenharmony_ci		val &= 0x3;
22562306a36Sopenharmony_ci		force_hpet_address = 0xFED00000 | (val << 12);
22662306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
22762306a36Sopenharmony_ci			force_hpet_address);
22862306a36Sopenharmony_ci		return;
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	/*
23262306a36Sopenharmony_ci	 * HPET is disabled. Trying enabling at FED00000 and check
23362306a36Sopenharmony_ci	 * whether it sticks
23462306a36Sopenharmony_ci	 */
23562306a36Sopenharmony_ci	gen_cntl &= (~(0x7 << 15));
23662306a36Sopenharmony_ci	gen_cntl |= (0x4 << 15);
23762306a36Sopenharmony_ci	pci_write_config_dword(dev, 0xD0, gen_cntl);
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	pci_read_config_dword(dev, 0xD0, &gen_cntl);
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_ci	val = gen_cntl >> 15;
24262306a36Sopenharmony_ci	val &= 0x7;
24362306a36Sopenharmony_ci	if (val & 0x4) {
24462306a36Sopenharmony_ci		/* HPET is enabled in HPTC. Just not reported by BIOS */
24562306a36Sopenharmony_ci		val &= 0x3;
24662306a36Sopenharmony_ci		force_hpet_address = 0xFED00000 | (val << 12);
24762306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
24862306a36Sopenharmony_ci			"0x%lx\n", force_hpet_address);
24962306a36Sopenharmony_ci		cached_dev = dev;
25062306a36Sopenharmony_ci		force_hpet_resume_type = OLD_ICH_FORCE_HPET_RESUME;
25162306a36Sopenharmony_ci		return;
25262306a36Sopenharmony_ci	}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
25562306a36Sopenharmony_ci}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/*
25862306a36Sopenharmony_ci * Undocumented chipset features. Make sure that the user enforced
25962306a36Sopenharmony_ci * this.
26062306a36Sopenharmony_ci */
26162306a36Sopenharmony_cistatic void old_ich_force_enable_hpet_user(struct pci_dev *dev)
26262306a36Sopenharmony_ci{
26362306a36Sopenharmony_ci	if (hpet_force_user)
26462306a36Sopenharmony_ci		old_ich_force_enable_hpet(dev);
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1,
26862306a36Sopenharmony_ci			 old_ich_force_enable_hpet_user);
26962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
27062306a36Sopenharmony_ci			 old_ich_force_enable_hpet_user);
27162306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,
27262306a36Sopenharmony_ci			 old_ich_force_enable_hpet_user);
27362306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,
27462306a36Sopenharmony_ci			 old_ich_force_enable_hpet_user);
27562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12,
27662306a36Sopenharmony_ci			 old_ich_force_enable_hpet_user);
27762306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0,
27862306a36Sopenharmony_ci			 old_ich_force_enable_hpet);
27962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_12,
28062306a36Sopenharmony_ci			 old_ich_force_enable_hpet);
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic void vt8237_force_hpet_resume(void)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	u32 val;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	if (!force_hpet_address || !cached_dev)
28862306a36Sopenharmony_ci		return;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	val = 0xfed00000 | 0x80;
29162306a36Sopenharmony_ci	pci_write_config_dword(cached_dev, 0x68, val);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	pci_read_config_dword(cached_dev, 0x68, &val);
29462306a36Sopenharmony_ci	if (val & 0x80)
29562306a36Sopenharmony_ci		printk(KERN_DEBUG "Force enabled HPET at resume\n");
29662306a36Sopenharmony_ci	else
29762306a36Sopenharmony_ci		BUG();
29862306a36Sopenharmony_ci}
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_cistatic void vt8237_force_enable_hpet(struct pci_dev *dev)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	u32 val;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	if (hpet_address || force_hpet_address)
30562306a36Sopenharmony_ci		return;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	if (!hpet_force_user) {
30862306a36Sopenharmony_ci		hpet_print_force_info();
30962306a36Sopenharmony_ci		return;
31062306a36Sopenharmony_ci	}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x68, &val);
31362306a36Sopenharmony_ci	/*
31462306a36Sopenharmony_ci	 * Bit 7 is HPET enable bit.
31562306a36Sopenharmony_ci	 * Bit 31:10 is HPET base address (contrary to what datasheet claims)
31662306a36Sopenharmony_ci	 */
31762306a36Sopenharmony_ci	if (val & 0x80) {
31862306a36Sopenharmony_ci		force_hpet_address = (val & ~0x3ff);
31962306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev, "HPET at 0x%lx\n",
32062306a36Sopenharmony_ci			force_hpet_address);
32162306a36Sopenharmony_ci		return;
32262306a36Sopenharmony_ci	}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	/*
32562306a36Sopenharmony_ci	 * HPET is disabled. Trying enabling at FED00000 and check
32662306a36Sopenharmony_ci	 * whether it sticks
32762306a36Sopenharmony_ci	 */
32862306a36Sopenharmony_ci	val = 0xfed00000 | 0x80;
32962306a36Sopenharmony_ci	pci_write_config_dword(dev, 0x68, val);
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x68, &val);
33262306a36Sopenharmony_ci	if (val & 0x80) {
33362306a36Sopenharmony_ci		force_hpet_address = (val & ~0x3ff);
33462306a36Sopenharmony_ci		dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
33562306a36Sopenharmony_ci			"0x%lx\n", force_hpet_address);
33662306a36Sopenharmony_ci		cached_dev = dev;
33762306a36Sopenharmony_ci		force_hpet_resume_type = VT8237_FORCE_HPET_RESUME;
33862306a36Sopenharmony_ci		return;
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	dev_printk(KERN_DEBUG, &dev->dev, "Failed to force enable HPET\n");
34262306a36Sopenharmony_ci}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235,
34562306a36Sopenharmony_ci			 vt8237_force_enable_hpet);
34662306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237,
34762306a36Sopenharmony_ci			 vt8237_force_enable_hpet);
34862306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700,
34962306a36Sopenharmony_ci			 vt8237_force_enable_hpet);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_cistatic void ati_force_hpet_resume(void)
35262306a36Sopenharmony_ci{
35362306a36Sopenharmony_ci	pci_write_config_dword(cached_dev, 0x14, 0xfed00000);
35462306a36Sopenharmony_ci	printk(KERN_DEBUG "Force enabled HPET at resume\n");
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_cistatic u32 ati_ixp4x0_rev(struct pci_dev *dev)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	int err = 0;
36062306a36Sopenharmony_ci	u32 d = 0;
36162306a36Sopenharmony_ci	u8  b = 0;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	err = pci_read_config_byte(dev, 0xac, &b);
36462306a36Sopenharmony_ci	b &= ~(1<<5);
36562306a36Sopenharmony_ci	err |= pci_write_config_byte(dev, 0xac, b);
36662306a36Sopenharmony_ci	err |= pci_read_config_dword(dev, 0x70, &d);
36762306a36Sopenharmony_ci	d |= 1<<8;
36862306a36Sopenharmony_ci	err |= pci_write_config_dword(dev, 0x70, d);
36962306a36Sopenharmony_ci	err |= pci_read_config_dword(dev, 0x8, &d);
37062306a36Sopenharmony_ci	d &= 0xff;
37162306a36Sopenharmony_ci	dev_printk(KERN_DEBUG, &dev->dev, "SB4X0 revision 0x%x\n", d);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	WARN_ON_ONCE(err);
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	return d;
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_cistatic void ati_force_enable_hpet(struct pci_dev *dev)
37962306a36Sopenharmony_ci{
38062306a36Sopenharmony_ci	u32 d, val;
38162306a36Sopenharmony_ci	u8  b;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	if (hpet_address || force_hpet_address)
38462306a36Sopenharmony_ci		return;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	if (!hpet_force_user) {
38762306a36Sopenharmony_ci		hpet_print_force_info();
38862306a36Sopenharmony_ci		return;
38962306a36Sopenharmony_ci	}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	d = ati_ixp4x0_rev(dev);
39262306a36Sopenharmony_ci	if (d  < 0x82)
39362306a36Sopenharmony_ci		return;
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_ci	/* base address */
39662306a36Sopenharmony_ci	pci_write_config_dword(dev, 0x14, 0xfed00000);
39762306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x14, &val);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	/* enable interrupt */
40062306a36Sopenharmony_ci	outb(0x72, 0xcd6); b = inb(0xcd7);
40162306a36Sopenharmony_ci	b |= 0x1;
40262306a36Sopenharmony_ci	outb(0x72, 0xcd6); outb(b, 0xcd7);
40362306a36Sopenharmony_ci	outb(0x72, 0xcd6); b = inb(0xcd7);
40462306a36Sopenharmony_ci	if (!(b & 0x1))
40562306a36Sopenharmony_ci		return;
40662306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x64, &d);
40762306a36Sopenharmony_ci	d |= (1<<10);
40862306a36Sopenharmony_ci	pci_write_config_dword(dev, 0x64, d);
40962306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x64, &d);
41062306a36Sopenharmony_ci	if (!(d & (1<<10)))
41162306a36Sopenharmony_ci		return;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	force_hpet_address = val;
41462306a36Sopenharmony_ci	force_hpet_resume_type = ATI_FORCE_HPET_RESUME;
41562306a36Sopenharmony_ci	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
41662306a36Sopenharmony_ci		   force_hpet_address);
41762306a36Sopenharmony_ci	cached_dev = dev;
41862306a36Sopenharmony_ci}
41962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS,
42062306a36Sopenharmony_ci			 ati_force_enable_hpet);
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci/*
42362306a36Sopenharmony_ci * Undocumented chipset feature taken from LinuxBIOS.
42462306a36Sopenharmony_ci */
42562306a36Sopenharmony_cistatic void nvidia_force_hpet_resume(void)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	pci_write_config_dword(cached_dev, 0x44, 0xfed00001);
42862306a36Sopenharmony_ci	printk(KERN_DEBUG "Force enabled HPET at resume\n");
42962306a36Sopenharmony_ci}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_cistatic void nvidia_force_enable_hpet(struct pci_dev *dev)
43262306a36Sopenharmony_ci{
43362306a36Sopenharmony_ci	u32 val;
43462306a36Sopenharmony_ci
43562306a36Sopenharmony_ci	if (hpet_address || force_hpet_address)
43662306a36Sopenharmony_ci		return;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	if (!hpet_force_user) {
43962306a36Sopenharmony_ci		hpet_print_force_info();
44062306a36Sopenharmony_ci		return;
44162306a36Sopenharmony_ci	}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	pci_write_config_dword(dev, 0x44, 0xfed00001);
44462306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x44, &val);
44562306a36Sopenharmony_ci	force_hpet_address = val & 0xfffffffe;
44662306a36Sopenharmony_ci	force_hpet_resume_type = NVIDIA_FORCE_HPET_RESUME;
44762306a36Sopenharmony_ci	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at 0x%lx\n",
44862306a36Sopenharmony_ci		force_hpet_address);
44962306a36Sopenharmony_ci	cached_dev = dev;
45062306a36Sopenharmony_ci}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci/* ISA Bridges */
45362306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0050,
45462306a36Sopenharmony_ci			nvidia_force_enable_hpet);
45562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0051,
45662306a36Sopenharmony_ci			nvidia_force_enable_hpet);
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci/* LPC bridges */
45962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0260,
46062306a36Sopenharmony_ci			nvidia_force_enable_hpet);
46162306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0360,
46262306a36Sopenharmony_ci			nvidia_force_enable_hpet);
46362306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0361,
46462306a36Sopenharmony_ci			nvidia_force_enable_hpet);
46562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0362,
46662306a36Sopenharmony_ci			nvidia_force_enable_hpet);
46762306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0363,
46862306a36Sopenharmony_ci			nvidia_force_enable_hpet);
46962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0364,
47062306a36Sopenharmony_ci			nvidia_force_enable_hpet);
47162306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0365,
47262306a36Sopenharmony_ci			nvidia_force_enable_hpet);
47362306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0366,
47462306a36Sopenharmony_ci			nvidia_force_enable_hpet);
47562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NVIDIA, 0x0367,
47662306a36Sopenharmony_ci			nvidia_force_enable_hpet);
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_civoid force_hpet_resume(void)
47962306a36Sopenharmony_ci{
48062306a36Sopenharmony_ci	switch (force_hpet_resume_type) {
48162306a36Sopenharmony_ci	case ICH_FORCE_HPET_RESUME:
48262306a36Sopenharmony_ci		ich_force_hpet_resume();
48362306a36Sopenharmony_ci		return;
48462306a36Sopenharmony_ci	case OLD_ICH_FORCE_HPET_RESUME:
48562306a36Sopenharmony_ci		old_ich_force_hpet_resume();
48662306a36Sopenharmony_ci		return;
48762306a36Sopenharmony_ci	case VT8237_FORCE_HPET_RESUME:
48862306a36Sopenharmony_ci		vt8237_force_hpet_resume();
48962306a36Sopenharmony_ci		return;
49062306a36Sopenharmony_ci	case NVIDIA_FORCE_HPET_RESUME:
49162306a36Sopenharmony_ci		nvidia_force_hpet_resume();
49262306a36Sopenharmony_ci		return;
49362306a36Sopenharmony_ci	case ATI_FORCE_HPET_RESUME:
49462306a36Sopenharmony_ci		ati_force_hpet_resume();
49562306a36Sopenharmony_ci		return;
49662306a36Sopenharmony_ci	default:
49762306a36Sopenharmony_ci		break;
49862306a36Sopenharmony_ci	}
49962306a36Sopenharmony_ci}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci/*
50262306a36Sopenharmony_ci * According to the datasheet e6xx systems have the HPET hardwired to
50362306a36Sopenharmony_ci * 0xfed00000
50462306a36Sopenharmony_ci */
50562306a36Sopenharmony_cistatic void e6xx_force_enable_hpet(struct pci_dev *dev)
50662306a36Sopenharmony_ci{
50762306a36Sopenharmony_ci	if (hpet_address || force_hpet_address)
50862306a36Sopenharmony_ci		return;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	force_hpet_address = 0xFED00000;
51162306a36Sopenharmony_ci	force_hpet_resume_type = NONE_FORCE_HPET_RESUME;
51262306a36Sopenharmony_ci	dev_printk(KERN_DEBUG, &dev->dev, "Force enabled HPET at "
51362306a36Sopenharmony_ci		"0x%lx\n", force_hpet_address);
51462306a36Sopenharmony_ci}
51562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E6XX_CU,
51662306a36Sopenharmony_ci			 e6xx_force_enable_hpet);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci/*
51962306a36Sopenharmony_ci * HPET MSI on some boards (ATI SB700/SB800) has side effect on
52062306a36Sopenharmony_ci * floppy DMA. Disable HPET MSI on such platforms.
52162306a36Sopenharmony_ci * See erratum #27 (Misinterpreted MSI Requests May Result in
52262306a36Sopenharmony_ci * Corrupted LPC DMA Data) in AMD Publication #46837,
52362306a36Sopenharmony_ci * "SB700 Family Product Errata", Rev. 1.0, March 2010.
52462306a36Sopenharmony_ci */
52562306a36Sopenharmony_cistatic void force_disable_hpet_msi(struct pci_dev *unused)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	hpet_msi_disable = true;
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ciDECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS,
53162306a36Sopenharmony_ci			 force_disable_hpet_msi);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci#endif
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci#if defined(CONFIG_PCI) && defined(CONFIG_NUMA)
53662306a36Sopenharmony_ci/* Set correct numa_node information for AMD NB functions */
53762306a36Sopenharmony_cistatic void quirk_amd_nb_node(struct pci_dev *dev)
53862306a36Sopenharmony_ci{
53962306a36Sopenharmony_ci	struct pci_dev *nb_ht;
54062306a36Sopenharmony_ci	unsigned int devfn;
54162306a36Sopenharmony_ci	u32 node;
54262306a36Sopenharmony_ci	u32 val;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	devfn = PCI_DEVFN(PCI_SLOT(dev->devfn), 0);
54562306a36Sopenharmony_ci	nb_ht = pci_get_slot(dev->bus, devfn);
54662306a36Sopenharmony_ci	if (!nb_ht)
54762306a36Sopenharmony_ci		return;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	pci_read_config_dword(nb_ht, 0x60, &val);
55062306a36Sopenharmony_ci	node = pcibus_to_node(dev->bus) | (val & 7);
55162306a36Sopenharmony_ci	/*
55262306a36Sopenharmony_ci	 * Some hardware may return an invalid node ID,
55362306a36Sopenharmony_ci	 * so check it first:
55462306a36Sopenharmony_ci	 */
55562306a36Sopenharmony_ci	if (node_online(node))
55662306a36Sopenharmony_ci		set_dev_node(&dev->dev, node);
55762306a36Sopenharmony_ci	pci_dev_put(nb_ht);
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB,
56162306a36Sopenharmony_ci			quirk_amd_nb_node);
56262306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP,
56362306a36Sopenharmony_ci			quirk_amd_nb_node);
56462306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL,
56562306a36Sopenharmony_ci			quirk_amd_nb_node);
56662306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC,
56762306a36Sopenharmony_ci			quirk_amd_nb_node);
56862306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_HT,
56962306a36Sopenharmony_ci			quirk_amd_nb_node);
57062306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MAP,
57162306a36Sopenharmony_ci			quirk_amd_nb_node);
57262306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM,
57362306a36Sopenharmony_ci			quirk_amd_nb_node);
57462306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC,
57562306a36Sopenharmony_ci			quirk_amd_nb_node);
57662306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_LINK,
57762306a36Sopenharmony_ci			quirk_amd_nb_node);
57862306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F0,
57962306a36Sopenharmony_ci			quirk_amd_nb_node);
58062306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F1,
58162306a36Sopenharmony_ci			quirk_amd_nb_node);
58262306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F2,
58362306a36Sopenharmony_ci			quirk_amd_nb_node);
58462306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3,
58562306a36Sopenharmony_ci			quirk_amd_nb_node);
58662306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4,
58762306a36Sopenharmony_ci			quirk_amd_nb_node);
58862306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F5,
58962306a36Sopenharmony_ci			quirk_amd_nb_node);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci#endif
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci#ifdef CONFIG_PCI
59462306a36Sopenharmony_ci/*
59562306a36Sopenharmony_ci * Processor does not ensure DRAM scrub read/write sequence
59662306a36Sopenharmony_ci * is atomic wrt accesses to CC6 save state area. Therefore
59762306a36Sopenharmony_ci * if a concurrent scrub read/write access is to same address
59862306a36Sopenharmony_ci * the entry may appear as if it is not written. This quirk
59962306a36Sopenharmony_ci * applies to Fam16h models 00h-0Fh
60062306a36Sopenharmony_ci *
60162306a36Sopenharmony_ci * See "Revision Guide" for AMD F16h models 00h-0fh,
60262306a36Sopenharmony_ci * document 51810 rev. 3.04, Nov 2013
60362306a36Sopenharmony_ci */
60462306a36Sopenharmony_cistatic void amd_disable_seq_and_redirect_scrub(struct pci_dev *dev)
60562306a36Sopenharmony_ci{
60662306a36Sopenharmony_ci	u32 val;
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	/*
60962306a36Sopenharmony_ci	 * Suggested workaround:
61062306a36Sopenharmony_ci	 * set D18F3x58[4:0] = 00h and set D18F3x5C[0] = 0b
61162306a36Sopenharmony_ci	 */
61262306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x58, &val);
61362306a36Sopenharmony_ci	if (val & 0x1F) {
61462306a36Sopenharmony_ci		val &= ~(0x1F);
61562306a36Sopenharmony_ci		pci_write_config_dword(dev, 0x58, val);
61662306a36Sopenharmony_ci	}
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	pci_read_config_dword(dev, 0x5C, &val);
61962306a36Sopenharmony_ci	if (val & BIT(0)) {
62062306a36Sopenharmony_ci		val &= ~BIT(0);
62162306a36Sopenharmony_ci		pci_write_config_dword(dev, 0x5c, val);
62262306a36Sopenharmony_ci	}
62362306a36Sopenharmony_ci}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ciDECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3,
62662306a36Sopenharmony_ci			amd_disable_seq_and_redirect_scrub);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci/* Ivy Bridge, Haswell, Broadwell */
62962306a36Sopenharmony_cistatic void quirk_intel_brickland_xeon_ras_cap(struct pci_dev *pdev)
63062306a36Sopenharmony_ci{
63162306a36Sopenharmony_ci	u32 capid0;
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	pci_read_config_dword(pdev, 0x84, &capid0);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	if (capid0 & 0x10)
63662306a36Sopenharmony_ci		enable_copy_mc_fragile();
63762306a36Sopenharmony_ci}
63862306a36Sopenharmony_ci
63962306a36Sopenharmony_ci/* Skylake */
64062306a36Sopenharmony_cistatic void quirk_intel_purley_xeon_ras_cap(struct pci_dev *pdev)
64162306a36Sopenharmony_ci{
64262306a36Sopenharmony_ci	u32 capid0, capid5;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	pci_read_config_dword(pdev, 0x84, &capid0);
64562306a36Sopenharmony_ci	pci_read_config_dword(pdev, 0x98, &capid5);
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	/*
64862306a36Sopenharmony_ci	 * CAPID0{7:6} indicate whether this is an advanced RAS SKU
64962306a36Sopenharmony_ci	 * CAPID5{8:5} indicate that various NVDIMM usage modes are
65062306a36Sopenharmony_ci	 * enabled, so memory machine check recovery is also enabled.
65162306a36Sopenharmony_ci	 */
65262306a36Sopenharmony_ci	if ((capid0 & 0xc0) == 0xc0 || (capid5 & 0x1e0))
65362306a36Sopenharmony_ci		enable_copy_mc_fragile();
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ci}
65662306a36Sopenharmony_ciDECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0ec3, quirk_intel_brickland_xeon_ras_cap);
65762306a36Sopenharmony_ciDECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2fc0, quirk_intel_brickland_xeon_ras_cap);
65862306a36Sopenharmony_ciDECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, quirk_intel_brickland_xeon_ras_cap);
65962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2083, quirk_intel_purley_xeon_ras_cap);
66062306a36Sopenharmony_ci#endif
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_cibool x86_apple_machine;
66362306a36Sopenharmony_ciEXPORT_SYMBOL(x86_apple_machine);
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_civoid __init early_platform_quirks(void)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	x86_apple_machine = dmi_match(DMI_SYS_VENDOR, "Apple Inc.") ||
66862306a36Sopenharmony_ci			    dmi_match(DMI_SYS_VENDOR, "Apple Computer, Inc.");
66962306a36Sopenharmony_ci}
670