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: I884cfcd8a53b111bc9434e47ef483dde64fcc1ed
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 1a75bd7..062f0ea 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;