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) */
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index a95198c..874c728 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -730,13 +730,6 @@
skip_phy_resume:
- if (!(readl_relaxed(USB_USBCMD) & CMD_RUN) &&
- (readl_relaxed(USB_PORTSC) & PORT_SUSPEND)) {
- writel_relaxed(readl_relaxed(USB_USBCMD) | CMD_RUN ,
- USB_USBCMD);
- dbg_log_event(NULL, "Set RS", readl_relaxed(USB_USBCMD));
- }
-
usb_hcd_resume_root_hub(hcd);
atomic_set(&mehci->in_lpm, 0);
@@ -1246,6 +1239,8 @@
mehci->ehci.susp_sof_bug = 1;
mehci->ehci.reset_sof_bug = 1;
+ mehci->ehci.resume_sof_bug = 1;
+
mehci->ehci.max_log2_irq_thresh = 6;
res = platform_get_resource_byname(pdev,
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 5754170..a0f995c 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -152,6 +152,7 @@
unsigned has_synopsys_hc_bug:1; /* Synopsys HC */
unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */
unsigned susp_sof_bug:1; /*Chip Idea HC*/
+ unsigned resume_sof_bug:1;/*Chip Idea HC*/
unsigned reset_sof_bug:1; /*Chip Idea HC*/
/* required for usb32 quirk */