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.c58
1 files changed, 26 insertions, 32 deletions
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 629a96813fd..caf87428ca4 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -13,6 +13,7 @@
13#include <linux/pci.h> 13#include <linux/pci.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/delay.h> 15#include <linux/delay.h>
16#include <linux/export.h>
16#include <linux/acpi.h> 17#include <linux/acpi.h>
17#include <linux/dmi.h> 18#include <linux/dmi.h>
18#include "pci-quirks.h" 19#include "pci-quirks.h"
@@ -36,6 +37,7 @@
36#define OHCI_INTRENABLE 0x10 37#define OHCI_INTRENABLE 0x10
37#define OHCI_INTRDISABLE 0x14 38#define OHCI_INTRDISABLE 0x14
38#define OHCI_FMINTERVAL 0x34 39#define OHCI_FMINTERVAL 0x34
40#define OHCI_HCFS (3 << 6) /* hc functional state */
39#define OHCI_HCR (1 << 0) /* host controller reset */ 41#define OHCI_HCR (1 << 0) /* host controller reset */
40#define OHCI_OCR (1 << 3) /* ownership change request */ 42#define OHCI_OCR (1 << 3) /* ownership change request */
41#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ 43#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */
@@ -465,6 +467,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
465{ 467{
466 void __iomem *base; 468 void __iomem *base;
467 u32 control; 469 u32 control;
470 u32 fminterval;
471 int cnt;
468 472
469 if (!mmio_resource_enabled(pdev, 0)) 473 if (!mmio_resource_enabled(pdev, 0))
470 return; 474 return;
@@ -497,41 +501,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
497 } 501 }
498#endif 502#endif
499 503
500 /* reset controller, preserving RWC (and possibly IR) */ 504 /* disable interrupts */
501 writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); 505 writel((u32) ~0, base + OHCI_INTRDISABLE);
502 readl(base + OHCI_CONTROL);
503 506
504 /* Some NVIDIA controllers stop working if kept in RESET for too long */ 507 /* Reset the USB bus, if the controller isn't already in RESET */
505 if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) { 508 if (control & OHCI_HCFS) {
506 u32 fminterval; 509 /* Go into RESET, preserving RWC (and possibly IR) */
507 int cnt; 510 writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
511 readl(base + OHCI_CONTROL);
508 512
509 /* drive reset for at least 50 ms (7.1.7.5) */ 513 /* drive bus reset for at least 50 ms (7.1.7.5) */
510 msleep(50); 514 msleep(50);
515 }
511 516
512 /* software reset of the controller, preserving HcFmInterval */ 517 /* software reset of the controller, preserving HcFmInterval */
513 fminterval = readl(base + OHCI_FMINTERVAL); 518 fminterval = readl(base + OHCI_FMINTERVAL);
514 writel(OHCI_HCR, base + OHCI_CMDSTATUS); 519 writel(OHCI_HCR, base + OHCI_CMDSTATUS);
515 520
516 /* reset requires max 10 us delay */ 521 /* reset requires max 10 us delay */
517 for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */ 522 for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */
518 if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) 523 if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
519 break; 524 break;
520 udelay(1); 525 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 } 526 }
527 writel(fminterval, base + OHCI_FMINTERVAL);
528 528
529 /* 529 /* Now the controller is safely in SUSPEND and nothing can wake it up */
530 * disable interrupts
531 */
532 writel(~(u32)0, base + OHCI_INTRDISABLE);
533 writel(~(u32)0, base + OHCI_INTRSTATUS);
534
535 iounmap(base); 530 iounmap(base);
536} 531}
537 532
@@ -626,7 +621,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
626 void __iomem *base, *op_reg_base; 621 void __iomem *base, *op_reg_base;
627 u32 hcc_params, cap, val; 622 u32 hcc_params, cap, val;
628 u8 offset, cap_length; 623 u8 offset, cap_length;
629 int wait_time, delta, count = 256/4; 624 int wait_time, count = 256/4;
630 625
631 if (!mmio_resource_enabled(pdev, 0)) 626 if (!mmio_resource_enabled(pdev, 0))
632 return; 627 return;
@@ -672,11 +667,10 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
672 writel(val, op_reg_base + EHCI_USBCMD); 667 writel(val, op_reg_base + EHCI_USBCMD);
673 668
674 wait_time = 2000; 669 wait_time = 2000;
675 delta = 100;
676 do { 670 do {
677 writel(0x3f, op_reg_base + EHCI_USBSTS); 671 writel(0x3f, op_reg_base + EHCI_USBSTS);
678 udelay(delta); 672 udelay(100);
679 wait_time -= delta; 673 wait_time -= 100;
680 val = readl(op_reg_base + EHCI_USBSTS); 674 val = readl(op_reg_base + EHCI_USBSTS);
681 if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) { 675 if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
682 break; 676 break;