]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/usb/host/ehci-pci.c
USB: ehci-orion: the Orion EHCI root hub does have a Transaction Translator
[karo-tx-linux.git] / drivers / usb / host / ehci-pci.c
index 4bc7970ba3ef5d208d6341fe958d8895fda2d6f5..5bb7f6bb13f340a80f5fbd746e515f792fabe370 100644 (file)
@@ -38,7 +38,7 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
                if ((temp & (3 << 13)) == (1 << 13)) {
                        temp &= 0x1fff;
                        ehci->debug = ehci_to_hcd(ehci)->regs + temp;
-                       temp = readl(&ehci->debug->control);
+                       temp = ehci_readl(ehci, &ehci->debug->control);
                        ehci_info(ehci, "debug port %d%s\n",
                                HCS_DEBUG_PORT(ehci->hcs_params),
                                (temp & DBGP_ENABLED)
@@ -58,8 +58,6 @@ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev)
        if (!retval)
                ehci_dbg(ehci, "MWI active\n");
 
-       ehci_port_power(ehci, 0);
-
        return 0;
 }
 
@@ -71,8 +69,24 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        u32                     temp;
        int                     retval;
 
+       switch (pdev->vendor) {
+       case PCI_VENDOR_ID_TOSHIBA_2:
+               /* celleb's companion chip */
+               if (pdev->device == 0x01b5) {
+#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
+                       ehci->big_endian_mmio = 1;
+#else
+                       ehci_warn(ehci,
+                                 "unsupported big endian Toshiba quirk\n");
+#endif
+               }
+               break;
+       }
+
        ehci->caps = hcd->regs;
-       ehci->regs = hcd->regs + HC_LENGTH(readl(&ehci->caps->hc_capbase));
+       ehci->regs = hcd->regs +
+               HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+
        dbg_hcs_params(ehci, "reset");
        dbg_hcc_params(ehci, "reset");
 
@@ -101,7 +115,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        }
 
        /* cache this readonly data; minimize chip reads */
-       ehci->hcs_params = readl(&ehci->caps->hcs_params);
+       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
 
        retval = ehci_halt(ehci);
        if (retval)
@@ -116,6 +130,7 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
        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;
@@ -133,16 +148,28 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
                 * fixed in newer silicon.
                 */
                case 0x0068:
-                       pci_read_config_dword(pdev, PCI_REVISION_ID, &temp);
-                       if ((temp & 0xff) < 0xa4)
+                       if (pdev->revision < 0xa4)
                                ehci->no_selective_suspend = 1;
                        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;
        }
 
-       if (ehci_is_TDI(ehci))
-               ehci_reset(ehci);
+       ehci_reset(ehci);
 
        /* at least the Genesys GL880S needs fixup here */
        temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
@@ -195,6 +222,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;
@@ -235,8 +263,8 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
                rc = -EINVAL;
                goto bail;
        }
-       writel (0, &ehci->regs->intr_enable);
-       (void)readl(&ehci->regs->intr_enable);
+       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) {
@@ -270,13 +298,13 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
        /* If CF is still set, we maintained PCI Vaux power.
         * Just undo the effect of ehci_pci_suspend().
         */
-       if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
+       if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
                int     mask = INTR_MASK;
 
-               if (!device_may_wakeup(&hcd->self.root_hub->dev))
+               if (!hcd->self.root_hub->do_remote_wakeup)
                        mask &= ~STS_PCD;
-               writel(mask, &ehci->regs->intr_enable);
-               readl(&ehci->regs->intr_enable);
+               ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+               ehci_readl(ehci, &ehci->regs->intr_enable);
                return 0;
        }
 
@@ -293,17 +321,17 @@ 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);
 
+       ehci_writel(ehci, ehci->command, &ehci->regs->command);
+       ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
+       ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
+
        /* here we "know" root ports should always stay powered */
        ehci_port_power(ehci, 1);
 
-       writel(ehci->command, &ehci->regs->command);
-       writel(FLAG_CF, &ehci->regs->configured_flag);
-       readl(&ehci->regs->command);    /* unblock posted writes */
-
        hcd->state = HC_STATE_SUSPENDED;
        return 0;
 }
@@ -326,8 +354,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 +379,7 @@ 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,
 };
 
 /*-------------------------------------------------------------------------*/