aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/pci-quirks.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/pci-quirks.c')
-rw-r--r--drivers/usb/host/pci-quirks.c125
1 files changed, 82 insertions, 43 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 3ef2c0cdf1db..9e81c26313f9 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -190,9 +190,10 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
190 msleep(10); 190 msleep(10);
191 } 191 }
192 if (wait_time <= 0) 192 if (wait_time <= 0)
193 printk(KERN_WARNING "%s %s: early BIOS handoff " 193 printk(KERN_WARNING "%s %s: BIOS handoff "
194 "failed (BIOS bug ?)\n", 194 "failed (BIOS bug ?) %08x\n",
195 pdev->dev.bus_id, "OHCI"); 195 pdev->dev.bus_id, "OHCI",
196 readl(base + OHCI_CONTROL));
196 197
197 /* reset controller, preserving RWC */ 198 /* reset controller, preserving RWC */
198 writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL); 199 writel(control & OHCI_CTRL_RWC, base + OHCI_CONTROL);
@@ -212,8 +213,9 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
212{ 213{
213 int wait_time, delta; 214 int wait_time, delta;
214 void __iomem *base, *op_reg_base; 215 void __iomem *base, *op_reg_base;
215 u32 hcc_params, val, temp; 216 u32 hcc_params, val;
216 u8 cap_length; 217 u8 offset, cap_length;
218 int count = 256/4;
217 219
218 if (!mmio_resource_enabled(pdev, 0)) 220 if (!mmio_resource_enabled(pdev, 0))
219 return; 221 return;
@@ -224,51 +226,88 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
224 226
225 cap_length = readb(base); 227 cap_length = readb(base);
226 op_reg_base = base + cap_length; 228 op_reg_base = base + cap_length;
227 hcc_params = readl(base + EHCI_HCC_PARAMS);
228 hcc_params = (hcc_params >> 8) & 0xff;
229 if (hcc_params) {
230 pci_read_config_dword(pdev,
231 hcc_params + EHCI_USBLEGSUP,
232 &val);
233 if (((val & 0xff) == 1) && (val & EHCI_USBLEGSUP_BIOS)) {
234 /*
235 * Ok, BIOS is in smm mode, try to hand off...
236 */
237 pci_read_config_dword(pdev,
238 hcc_params + EHCI_USBLEGCTLSTS,
239 &temp);
240 pci_write_config_dword(pdev,
241 hcc_params + EHCI_USBLEGCTLSTS,
242 temp | EHCI_USBLEGCTLSTS_SOOE);
243 val |= EHCI_USBLEGSUP_OS;
244 pci_write_config_dword(pdev,
245 hcc_params + EHCI_USBLEGSUP,
246 val);
247 229
248 wait_time = 500; 230 /* EHCI 0.96 and later may have "extended capabilities"
249 do { 231 * spec section 5.1 explains the bios handoff, e.g. for
250 msleep(10); 232 * booting from USB disk or using a usb keyboard
251 wait_time -= 10; 233 */
234 hcc_params = readl(base + EHCI_HCC_PARAMS);
235 offset = (hcc_params >> 8) & 0xff;
236 while (offset && count--) {
237 u32 cap;
238 int msec;
239
240 pci_read_config_dword(pdev, offset, &cap);
241 switch (cap & 0xff) {
242 case 1: /* BIOS/SMM/... handoff support */
243 if ((cap & EHCI_USBLEGSUP_BIOS)) {
244 pr_debug("%s %s: BIOS handoff\n",
245 pdev->dev.bus_id, "EHCI");
246
247#if 0
248/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on,
249 * but that seems dubious in general (the BIOS left it off intentionally)
250 * and is known to prevent some systems from booting. so we won't do this
251 * unless maybe we can determine when we're on a system that needs SMI forced.
252 */
253 /* BIOS workaround (?): be sure the
254 * pre-Linux code receives the SMI
255 */
252 pci_read_config_dword(pdev, 256 pci_read_config_dword(pdev,
253 hcc_params + EHCI_USBLEGSUP, 257 offset + EHCI_USBLEGCTLSTS,
254 &val); 258 &val);
255 } while (wait_time && (val & EHCI_USBLEGSUP_BIOS));
256 if (!wait_time) {
257 /*
258 * well, possibly buggy BIOS...
259 */
260 printk(KERN_WARNING "%s %s: early BIOS handoff "
261 "failed (BIOS bug ?)\n",
262 pdev->dev.bus_id, "EHCI");
263 pci_write_config_dword(pdev, 259 pci_write_config_dword(pdev,
264 hcc_params + EHCI_USBLEGSUP, 260 offset + EHCI_USBLEGCTLSTS,
265 EHCI_USBLEGSUP_OS); 261 val | EHCI_USBLEGCTLSTS_SOOE);
266 pci_write_config_dword(pdev, 262#endif
267 hcc_params + EHCI_USBLEGCTLSTS, 263
268 0); 264 /* some systems get upset if this semaphore is
265 * set for any other reason than forcing a BIOS
266 * handoff..
267 */
268 pci_write_config_byte(pdev, offset + 3, 1);
269 }
270
271 /* if boot firmware now owns EHCI, spin till
272 * it hands it over.
273 */
274 msec = 5000;
275 while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) {
276 msleep(10);
277 msec -= 10;
278 pci_read_config_dword(pdev, offset, &cap);
279 }
280
281 if (cap & EHCI_USBLEGSUP_BIOS) {
282 /* well, possibly buggy BIOS... try to shut
283 * it down, and hope nothing goes too wrong
284 */
285 printk(KERN_WARNING "%s %s: BIOS handoff "
286 "failed (BIOS bug ?) %08x\n",
287 pdev->dev.bus_id, "EHCI", cap);
288 pci_write_config_byte(pdev, offset + 2, 0);
269 } 289 }
290
291 /* just in case, always disable EHCI SMIs */
292 pci_write_config_dword(pdev,
293 offset + EHCI_USBLEGCTLSTS,
294 0);
295 break;
296 case 0: /* illegal reserved capability */
297 cap = 0;
298 /* FALLTHROUGH */
299 default:
300 printk(KERN_WARNING "%s %s: unrecognized "
301 "capability %02x\n",
302 pdev->dev.bus_id, "EHCI",
303 cap & 0xff);
304 break;
270 } 305 }
306 offset = (cap >> 8) & 0xff;
271 } 307 }
308 if (!count)
309 printk(KERN_DEBUG "%s %s: capability loop?\n",
310 pdev->dev.bus_id, "EHCI");
272 311
273 /* 312 /*
274 * halt EHCI & disable its interrupts in any case 313 * halt EHCI & disable its interrupts in any case