Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394...
[pandora-kernel.git] / drivers / usb / host / xhci.c
index 40e0a0c..27345cd 100644 (file)
@@ -105,6 +105,33 @@ int xhci_halt(struct xhci_hcd *xhci)
                        STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC);
 }
 
+/*
+ * Set the run bit and wait for the host to be running.
+ */
+int xhci_start(struct xhci_hcd *xhci)
+{
+       u32 temp;
+       int ret;
+
+       temp = xhci_readl(xhci, &xhci->op_regs->command);
+       temp |= (CMD_RUN);
+       xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
+                       temp);
+       xhci_writel(xhci, temp, &xhci->op_regs->command);
+
+       /*
+        * Wait for the HCHalted Status bit to be 0 to indicate the host is
+        * running.
+        */
+       ret = handshake(xhci, &xhci->op_regs->status,
+                       STS_HALT, 0, XHCI_MAX_HALT_USEC);
+       if (ret == -ETIMEDOUT)
+               xhci_err(xhci, "Host took too long to start, "
+                               "waited %u microseconds.\n",
+                               XHCI_MAX_HALT_USEC);
+       return ret;
+}
+
 /*
  * Reset a halted HC, and set the internal HC state to HC_STATE_HALT.
  *
@@ -116,6 +143,7 @@ int xhci_reset(struct xhci_hcd *xhci)
 {
        u32 command;
        u32 state;
+       int ret;
 
        state = xhci_readl(xhci, &xhci->op_regs->status);
        if ((state & STS_HALT) == 0) {
@@ -130,7 +158,17 @@ int xhci_reset(struct xhci_hcd *xhci)
        /* XXX: Why does EHCI set this here?  Shouldn't other code do this? */
        xhci_to_hcd(xhci)->state = HC_STATE_HALT;
 
-       return handshake(xhci, &xhci->op_regs->command, CMD_RESET, 0, 250 * 1000);
+       ret = handshake(xhci, &xhci->op_regs->command,
+                       CMD_RESET, 0, 250 * 1000);
+       if (ret)
+               return ret;
+
+       xhci_dbg(xhci, "Wait for controller to be ready for doorbell rings\n");
+       /*
+        * xHCI cannot write to any doorbells or operational registers other
+        * than status until the "Controller Not Ready" flag is cleared.
+        */
+       return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000);
 }
 
 
@@ -448,17 +486,20 @@ int xhci_run(struct usb_hcd *hcd)
 
        if (NUM_TEST_NOOPS > 0)
                doorbell = xhci_setup_one_noop(xhci);
+       if (xhci->quirks & XHCI_NEC_HOST)
+               xhci_queue_vendor_command(xhci, 0, 0, 0,
+                               TRB_TYPE(TRB_NEC_GET_FW));
+
+       if (xhci_start(xhci)) {
+               xhci_halt(xhci);
+               return -ENODEV;
+       }
 
-       temp = xhci_readl(xhci, &xhci->op_regs->command);
-       temp |= (CMD_RUN);
-       xhci_dbg(xhci, "// Turn on HC, cmd = 0x%x.\n",
-                       temp);
-       xhci_writel(xhci, temp, &xhci->op_regs->command);
-       /* Flush PCI posted writes */
-       temp = xhci_readl(xhci, &xhci->op_regs->command);
        xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
        if (doorbell)
                (*doorbell)(xhci);
+       if (xhci->quirks & XHCI_NEC_HOST)
+               xhci_ring_cmd_db(xhci);
 
        xhci_dbg(xhci, "Finished xhci_run\n");
        return 0;