ARM: 5682/1: Add cpu.c and dev.c and modify some files of w90p910 platform
[safe/jmp/linux-2.6] / drivers / usb / host / ehci-pci.c
index ad0d496..f3683e1 100644 (file)
@@ -66,6 +66,8 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+       struct pci_dev          *p_smbus;
+       u8                      rev;
        u32                     temp;
        int                     retval;
 
@@ -106,7 +108,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                case 0x00d8:    /* CK8 */
                case 0x00e8:    /* CK8S */
                        if (pci_set_consistent_dma_mask(pdev,
-                                               DMA_31BIT_MASK) < 0)
+                                               DMA_BIT_MASK(31)) < 0)
                                ehci_warn(ehci, "can't enable NVidia "
                                        "workaround for >2GB RAM\n");
                        break;
@@ -129,7 +131,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        switch (pdev->vendor) {
        case PCI_VENDOR_ID_TDI:
                if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
-                       ehci->is_tdi_rh_tt = 1;
+                       hcd->has_tt = 1;
                        tdi_reset(ehci);
                }
                break;
@@ -152,6 +154,42 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                        break;
                }
                break;
+       case PCI_VENDOR_ID_VIA:
+               if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x60) {
+                       u8 tmp;
+
+                       /* The VT6212 defaults to a 1 usec EHCI sleep time which
+                        * hogs the PCI bus *badly*. Setting bit 5 of 0x4B makes
+                        * that sleep time use the conventional 10 usec.
+                        */
+                       pci_read_config_byte(pdev, 0x4b, &tmp);
+                       if (tmp & 0x20)
+                               break;
+                       pci_write_config_byte(pdev, 0x4b, tmp | 0x20);
+               }
+               break;
+       case PCI_VENDOR_ID_ATI:
+               /* SB600 and old version of SB700 have a bug in EHCI controller,
+                * which causes usb devices lose response in some cases.
+                */
+               if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) {
+                       p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
+                                                PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+                                                NULL);
+                       if (!p_smbus)
+                               break;
+                       rev = p_smbus->revision;
+                       if ((pdev->device == 0x4386) || (rev == 0x3a)
+                           || (rev == 0x3b)) {
+                               u8 tmp;
+                               ehci_info(ehci, "applying AMD SB600/SB700 USB "
+                                       "freeze workaround\n");
+                               pci_read_config_byte(pdev, 0x53, &tmp);
+                               pci_write_config_byte(pdev, 0x53, tmp | (1<<3));
+                       }
+                       pci_dev_put(p_smbus);
+               }
+               break;
        }
 
        ehci_reset(ehci);
@@ -181,15 +219,19 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        /* Serial Bus Release Number is at PCI 0x60 offset */
        pci_read_config_byte(pdev, 0x60, &ehci->sbrn);
 
-       /* Workaround current PCI init glitch:  wakeup bits aren't
-        * being set from PCI PM capability.
+       /* Keep this around for a while just in case some EHCI
+        * implementation uses legacy PCI PM support.  This test
+        * can be removed on 17 Dec 2009 if the dev_warn() hasn't
+        * been triggered by then.
         */
        if (!device_can_wakeup(&pdev->dev)) {
                u16     port_wake;
 
                pci_read_config_word(pdev, 0x62, &port_wake);
-               if (port_wake & 0x0001)
-                       device_init_wakeup(&pdev->dev, 1);
+               if (port_wake & 0x0001) {
+                       dev_warn(&pdev->dev, "Enabling legacy PCI PM\n");
+                       device_set_wakeup_capable(&pdev->dev, 1);
+               }
        }
 
 #ifdef CONFIG_USB_SUSPEND
@@ -207,6 +249,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                ehci_warn(ehci, "selective suspend/wakeup unavailable\n");
 #endif
 
+       ehci_port_power(ehci, 1);
        retval = ehci_pci_reinit(ehci, pdev);
 done:
        return retval;
@@ -225,7 +268,7 @@ done:
  * Also they depend on separate root hub suspend/resume.
  */
 
-static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
+static int ehci_pci_suspend(struct usb_hcd *hcd)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        unsigned long           flags;
@@ -250,12 +293,6 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
        ehci_writel(ehci, 0, &ehci->regs->intr_enable);
        (void)ehci_readl(ehci, &ehci->regs->intr_enable);
 
-       /* make sure snapshot being resumed re-enumerates everything */
-       if (message.event == PM_EVENT_PRETHAW) {
-               ehci_halt(ehci);
-               ehci_reset(ehci);
-       }
-
        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
  bail:
        spin_unlock_irqrestore (&ehci->lock, flags);
@@ -266,7 +303,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
        return rc;
 }
 
-static int ehci_pci_resume(struct usb_hcd *hcd)
+static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci(hcd);
        struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
@@ -279,20 +316,21 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
        /* Mark hardware accessible again as we are out of D3 state by now */
        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
-       /* If CF is still set, we maintained PCI Vaux power.
+       /* If CF is still set and we aren't resuming from hibernation
+        * then we maintained PCI Vaux power.
         * Just undo the effect of ehci_pci_suspend().
         */
-       if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
+       if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
+                               !hibernated) {
                int     mask = INTR_MASK;
 
-               if (!device_may_wakeup(&hcd->self.root_hub->dev))
+               if (!hcd->self.root_hub->do_remote_wakeup)
                        mask &= ~STS_PCD;
                ehci_writel(ehci, mask, &ehci->regs->intr_enable);
                ehci_readl(ehci, &ehci->regs->intr_enable);
                return 0;
        }
 
-       ehci_dbg(ehci, "lost power, restarting\n");
        usb_root_hub_lost_power(hcd->self.root_hub);
 
        /* Else reset, to cope with power loss or flush-to-storage
@@ -305,7 +343,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
        /* emptying the schedule aborts any urbs */
        spin_lock_irq(&ehci->lock);
        if (ehci->reclaim)
-               ehci->reclaim_ready = 1;
+               end_unlink_async(ehci);
        ehci_work(ehci);
        spin_unlock_irq(&ehci->lock);
 
@@ -315,7 +353,6 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
 
        /* here we "know" root ports should always stay powered */
        ehci_port_power(ehci, 1);
-       ehci_handover_companion_ports(ehci);
 
        hcd->state = HC_STATE_SUSPENDED;
        return 0;
@@ -339,8 +376,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .reset =                ehci_pci_setup,
        .start =                ehci_run,
 #ifdef CONFIG_PM
-       .suspend =              ehci_pci_suspend,
-       .resume =               ehci_pci_resume,
+       .pci_suspend =          ehci_pci_suspend,
+       .pci_resume =           ehci_pci_resume,
 #endif
        .stop =                 ehci_stop,
        .shutdown =             ehci_shutdown,
@@ -351,6 +388,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .urb_enqueue =          ehci_urb_enqueue,
        .urb_dequeue =          ehci_urb_dequeue,
        .endpoint_disable =     ehci_endpoint_disable,
+       .endpoint_reset =       ehci_endpoint_reset,
 
        /*
         * scheduling support
@@ -364,6 +402,8 @@ static const struct hc_driver ehci_pci_hc_driver = {
        .hub_control =          ehci_hub_control,
        .bus_suspend =          ehci_bus_suspend,
        .bus_resume =           ehci_bus_resume,
+       .relinquish_port =      ehci_relinquish_port,
+       .port_handed_over =     ehci_port_handed_over,
 };
 
 /*-------------------------------------------------------------------------*/
@@ -385,10 +425,11 @@ static struct pci_driver ehci_pci_driver = {
 
        .probe =        usb_hcd_pci_probe,
        .remove =       usb_hcd_pci_remove,
+       .shutdown =     usb_hcd_pci_shutdown,
 
-#ifdef CONFIG_PM
-       .suspend =      usb_hcd_pci_suspend,
-       .resume =       usb_hcd_pci_resume,
+#ifdef CONFIG_PM_SLEEP
+       .driver =       {
+               .pm =   &usb_hcd_pci_pm_ops
+       },
 #endif
-       .shutdown =     usb_hcd_pci_shutdown,
 };