|
@@ -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.
|
|
|
*
|
|
@@ -460,13 +487,11 @@ int xhci_run(struct usb_hcd *hcd)
|
|
|
if (NUM_TEST_NOOPS > 0)
|
|
|
doorbell = xhci_setup_one_noop(xhci);
|
|
|
|
|
|
- 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);
|
|
|
+ if (xhci_start(xhci)) {
|
|
|
+ xhci_halt(xhci);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+
|
|
|
xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp);
|
|
|
if (doorbell)
|
|
|
(*doorbell)(xhci);
|