diff options
Diffstat (limited to 'drivers/usb/host/pci-quirks.c')
-rw-r--r-- | drivers/usb/host/pci-quirks.c | 56 |
1 files changed, 49 insertions, 7 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index fd930618c28f..a9d315906e3d 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #define OHCI_INTRSTATUS 0x0c | 35 | #define OHCI_INTRSTATUS 0x0c |
36 | #define OHCI_INTRENABLE 0x10 | 36 | #define OHCI_INTRENABLE 0x10 |
37 | #define OHCI_INTRDISABLE 0x14 | 37 | #define OHCI_INTRDISABLE 0x14 |
38 | #define OHCI_FMINTERVAL 0x34 | ||
39 | #define OHCI_HCR (1 << 0) /* host controller reset */ | ||
38 | #define OHCI_OCR (1 << 3) /* ownership change request */ | 40 | #define OHCI_OCR (1 << 3) /* ownership change request */ |
39 | #define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ | 41 | #define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ |
40 | #define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ | 42 | #define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ |
@@ -497,6 +499,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | |||
497 | 499 | ||
498 | /* reset controller, preserving RWC (and possibly IR) */ | 500 | /* reset controller, preserving RWC (and possibly IR) */ |
499 | writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); | 501 | writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); |
502 | readl(base + OHCI_CONTROL); | ||
503 | |||
504 | /* Some NVIDIA controllers stop working if kept in RESET for too long */ | ||
505 | if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { | ||
506 | u32 fminterval; | ||
507 | int cnt; | ||
508 | |||
509 | /* drive reset for at least 50 ms (7.1.7.5) */ | ||
510 | msleep(50); | ||
511 | |||
512 | /* software reset of the controller, preserving HcFmInterval */ | ||
513 | fminterval = readl(base + OHCI_FMINTERVAL); | ||
514 | writel(OHCI_HCR, base + OHCI_CMDSTATUS); | ||
515 | |||
516 | /* reset requires max 10 us delay */ | ||
517 | for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */ | ||
518 | if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) | ||
519 | break; | ||
520 | udelay(1); | ||
521 | } | ||
522 | writel(fminterval, base + OHCI_FMINTERVAL); | ||
523 | |||
524 | /* Now we're in the SUSPEND state with all devices reset | ||
525 | * and wakeups and interrupts disabled | ||
526 | */ | ||
527 | } | ||
500 | 528 | ||
501 | /* | 529 | /* |
502 | * disable interrupts | 530 | * disable interrupts |
@@ -507,20 +535,34 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev) | |||
507 | iounmap(base); | 535 | iounmap(base); |
508 | } | 536 | } |
509 | 537 | ||
538 | static const struct dmi_system_id __initconst ehci_dmi_nohandoff_table[] = { | ||
539 | { | ||
540 | /* Pegatron Lucid (ExoPC) */ | ||
541 | .matches = { | ||
542 | DMI_MATCH(DMI_BOARD_NAME, "EXOPG06411"), | ||
543 | DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"), | ||
544 | }, | ||
545 | }, | ||
546 | { | ||
547 | /* Pegatron Lucid (Ordissimo AIRIS) */ | ||
548 | .matches = { | ||
549 | DMI_MATCH(DMI_BOARD_NAME, "M11JB"), | ||
550 | DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), | ||
551 | }, | ||
552 | }, | ||
553 | { } | ||
554 | }; | ||
555 | |||
510 | static void __devinit ehci_bios_handoff(struct pci_dev *pdev, | 556 | static void __devinit ehci_bios_handoff(struct pci_dev *pdev, |
511 | void __iomem *op_reg_base, | 557 | void __iomem *op_reg_base, |
512 | u32 cap, u8 offset) | 558 | u32 cap, u8 offset) |
513 | { | 559 | { |
514 | int try_handoff = 1, tried_handoff = 0; | 560 | int try_handoff = 1, tried_handoff = 0; |
515 | 561 | ||
516 | /* The Pegatron Lucid (ExoPC) tablet sporadically waits for 90 | 562 | /* The Pegatron Lucid tablet sporadically waits for 98 seconds trying |
517 | * seconds trying the handoff on its unused controller. Skip | 563 | * the handoff on its unused controller. Skip it. */ |
518 | * it. */ | ||
519 | if (pdev->vendor == 0x8086 && pdev->device == 0x283a) { | 564 | if (pdev->vendor == 0x8086 && pdev->device == 0x283a) { |
520 | const char *dmi_bn = dmi_get_system_info(DMI_BOARD_NAME); | 565 | if (dmi_check_system(ehci_dmi_nohandoff_table)) |
521 | const char *dmi_bv = dmi_get_system_info(DMI_BIOS_VERSION); | ||
522 | if (dmi_bn && !strcmp(dmi_bn, "EXOPG06411") && | ||
523 | dmi_bv && !strcmp(dmi_bv, "Lucid-CE-133")) | ||
524 | try_handoff = 0; | 566 | try_handoff = 0; |
525 | } | 567 | } |
526 | 568 | ||