EHCI: HSIC: Set RUN/STOP bit after PORT_RESUME gets cleared
There is a possibility of HSIC phy getting locked up if RUN/STOP
bit is set before finishing the resume signaling. Hence do not
set the RUN/STOP bit before setting PORT_RESUME bit. Since
PORT_RESUME bit gets cleared automatically by HSIC HW after bus
resume is completed, need to set RUN/STOP bit right after that.
CRs-Fixed: 372145
Change-Id: Icb9effefe14c10f13cfbb3d8f1840c8bdd96aea4
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 3098fbe..fff9465 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -380,6 +380,9 @@
ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next);
+ /*CMD_RUN will be set after, PORT_RESUME gets cleared*/
+ if (ehci->resume_sof_bug)
+ ehci->command &= ~CMD_RUN;
/* restore CMD_RUN, framelist size, and irq threshold */
ehci_writel(ehci, ehci->command, &ehci->regs->command);
ehci->rh_state = EHCI_RH_RUNNING;
@@ -422,6 +425,17 @@
ehci_writel(ehci, temp, &ehci->regs->port_status [i]);
}
+ if (ehci->resume_sof_bug && resume_needed) {
+ /* root hub has only one port.
+ * PORT_RESUME gets cleared automatically. */
+ handshake(ehci, &ehci->regs->port_status[0], PORT_RESUME, 0,
+ 20000);
+ ehci_writel(ehci, ehci_readl(ehci,
+ &ehci->regs->command) | CMD_RUN,
+ &ehci->regs->command);
+ goto skip_clear_resume;
+ }
+
/* msleep for 20ms only if code is trying to resume port */
if (resume_needed) {
spin_unlock_irq(&ehci->lock);
@@ -438,6 +452,8 @@
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
}
}
+
+skip_clear_resume:
(void) ehci_readl(ehci, &ehci->regs->command);
/* maybe re-activate the schedule(s) */