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