]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/usb/host/ehci-pci.c
USB: EHCI: Disable langwell/penwell LPM capability
[net-next-2.6.git] / drivers / usb / host / ehci-pci.c
index d43d176161aab6e6a7377a91c8b8e92e2cd87130..a1e8d273103f77b2d237a5f68438b289b51bb92a 100644 (file)
@@ -114,10 +114,16 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                break;
        case PCI_VENDOR_ID_INTEL:
                ehci->need_io_watchdog = 0;
+               ehci->fs_i_thresh = 1;
                if (pdev->device == 0x27cc) {
                        ehci->broken_periodic = 1;
                        ehci_info(ehci, "using broken periodic workaround\n");
                }
+               if (pdev->device == 0x0806 || pdev->device == 0x0811
+                               || pdev->device == 0x0829) {
+                       ehci_info(ehci, "disable lpm for langwell/penwell\n");
+                       ehci->has_lpm = 0;
+               }
                break;
        case PCI_VENDOR_ID_TDI:
                if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
@@ -277,7 +283,7 @@ done:
  * Also they depend on separate root hub suspend/resume.
  */
 
-static int ehci_pci_suspend(struct usb_hcd *hcd)
+static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        unsigned long           flags;
@@ -291,7 +297,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd)
         * the root hub is either suspended or stopped.
         */
        spin_lock_irqsave (&ehci->lock, flags);
-       ehci_prepare_ports_for_controller_suspend(ehci);
+       ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
        ehci_writel(ehci, 0, &ehci->regs->intr_enable);
        (void)ehci_readl(ehci, &ehci->regs->intr_enable);
 
@@ -361,6 +367,22 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 }
 #endif
 
+static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+       int rc = 0;
+
+       if (!udev->parent) /* udev is root hub itself, impossible */
+               rc = -1;
+       /* we only support lpm device connected to root hub yet */
+       if (ehci->has_lpm && !udev->parent->parent) {
+               rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum);
+               if (!rc)
+                       rc = ehci_lpm_check(ehci, udev->portnum);
+       }
+       return rc;
+}
+
 static const struct hc_driver ehci_pci_hc_driver = {
        .description =          hcd_name,
        .product_desc =         "EHCI Host Controller",
@@ -407,6 +429,11 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .relinquish_port =      ehci_relinquish_port,
        .port_handed_over =     ehci_port_handed_over,
 
+       /*
+        * call back when device connected and addressed
+        */
+       .update_device =        ehci_update_device,
+
        .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };