EHCI: HSIC: Implement new reset sequence to workaround PHY lockup issue

commit 8e6edcb (usb: ehci: Avoid phy lockup due to SOFs during port
reset) implements a workaround for PHY lockup issue during port reset.
The workaround relies on a hardware debug feature which allows driving
strobe and data lines to reset using ULPI interface.  This is not
working some times for unknown reason.

This patch implements a new reset sequence to workaround the PHY lockup
issue.  The controller drive reset signaling for ~50 msec when reset bit
is set in PORTSC register.  The controller automatically clears this bit
after finishing the reset signaling.  The software can also finish the
reset signaling any time by clearing the reset bit.

According to USB2 spec, Host controller should drive reset signaling for
50 msec for root hub ports.  But HSIC spec allows shorter reset signaling
time (20 msec).  Clear the reset bit in PORTSC register after 20 msec and
start controller immediately to send SOF.  Use controller internal timers
to achieve this.  If reset bit is not cleared in time, perform the sequence
in a loop with interrupts disabled.

CRs-Fixed: 445659
Change-Id: I6b251ced8d47b9ece4a06e58baf15c69a8bb340f
Signed-off-by: Pavankumar Kondeti <pkondeti@codeaurora.org>
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index fff9465..cfdb688 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -839,7 +839,7 @@
 	u32 __iomem	*status_reg = &ehci->regs->port_status[
 				(wIndex & 0xff) - 1];
 	u32 __iomem	*hostpc_reg = NULL;
-	u32		temp, temp1, status, cmd = 0;
+	u32		temp, temp1, status;
 	unsigned long	flags;
 	int		retval = 0;
 	unsigned	selector;
@@ -1218,31 +1218,13 @@
 				ehci->reset_done [wIndex] = jiffies
 						+ msecs_to_jiffies (50);
 			}
-
-			if (ehci->reset_sof_bug && (temp & PORT_RESET)) {
-				cmd = ehci_readl(ehci, &ehci->regs->command);
-				cmd &= ~CMD_RUN;
-				ehci_writel(ehci, cmd, &ehci->regs->command);
-				if (handshake(ehci, &ehci->regs->status,
-						STS_HALT, STS_HALT, 16 * 125))
-					ehci_info(ehci,
-						"controller halt failed\n");
-			}
-			ehci_writel(ehci, temp, status_reg);
-			if (ehci->reset_sof_bug && (temp & PORT_RESET)
-				&& hcd->driver->enable_ulpi_control) {
-				hcd->driver->enable_ulpi_control(hcd,
-						PORT_RESET);
+			if (ehci->reset_sof_bug && (temp & PORT_RESET) &&
+					hcd->driver->reset_sof_bug_handler) {
 				spin_unlock_irqrestore(&ehci->lock, flags);
-				usleep_range(50000, 55000);
-				if (handshake(ehci, status_reg,
-						PORT_RESET, 0, 10 * 1000))
-					ehci_info(ehci,
-						"failed to clear reset\n");
+				hcd->driver->reset_sof_bug_handler(hcd, temp);
 				spin_lock_irqsave(&ehci->lock, flags);
-				hcd->driver->disable_ulpi_control(hcd);
-				cmd |= CMD_RUN;
-				ehci_writel(ehci, cmd, &ehci->regs->command);
+			} else {
+				ehci_writel(ehci, temp, status_reg);
 			}
 			break;