summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamneek Mehresh <ramneek.mehresh@freescale.com>2013-04-11 11:35:29 (GMT)
committerXie Xiaobo <xiaobo.xie@nxp.com>2017-09-25 07:25:27 (GMT)
commitbb40cce21a9f174d07ea82173e5fe59cfbdbaaca (patch)
tree75f80cfcfd17a9c76ba4accf4685cd2602482626
parent14b69bb2d73140b536a29435544045fe386999fe (diff)
downloadlinux-bb40cce21a9f174d07ea82173e5fe59cfbdbaaca.tar.xz
usb: gadget: Add host-gadget drv sync delay
Resolve synchronization issue between host and gadget drivers upon role-reversal Signed-off-by: Ramneek Mehresh <ramneek.mehresh@freescale.com> Signed-off-by: yinbo.zhu <yinbo.zhu@nxp.com>
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c16
-rw-r--r--drivers/usb/gadget/udc/fsl_usb2_udc.h1
2 files changed, 17 insertions, 0 deletions
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index b0d0822..5afba93 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -1775,6 +1775,7 @@ static void suspend_irq(struct fsl_udc *udc)
static void bus_resume(struct fsl_udc *udc)
{
+ udc->last_state = udc->usb_state;
udc->usb_state = udc->resume_state;
udc->resume_state = 0;
@@ -2610,6 +2611,21 @@ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state)
*-----------------------------------------------------------------*/
static int fsl_udc_resume(struct platform_device *pdev)
{
+#if defined(CONFIG_FSL_USB2_OTG) || defined(CONFIG_FSL_USB2_OTG_MODULE)
+ /* Add delay to synchronize between host and gadget drivers
+ * Upon role-reversal host drv is shutdown by kernel worker
+ * thread. By the time host drv shuts down, dr controller
+ * gets programmed for gadget role. Shutting host drv after this
+ * results in controller getting reset, and it stops responding
+ * to otg events
+ *
+ * This delay can be added only if this function call is not in
+ * interrupt context which happens only when USB device is not
+ * coming out of SUSPEND state
+ */
+ if (udc_controller->last_state != USB_STATE_SUSPENDED)
+ msleep(1000);
+#endif
/* Enable DR irq reg and set controller Run */
if (udc_controller->stopped) {
dr_controller_setup(udc_controller);
diff --git a/drivers/usb/gadget/udc/fsl_usb2_udc.h b/drivers/usb/gadget/udc/fsl_usb2_udc.h
index 8471562..d92ea5a 100644
--- a/drivers/usb/gadget/udc/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/udc/fsl_usb2_udc.h
@@ -503,6 +503,7 @@ struct fsl_udc {
u32 max_pipes; /* Device max pipes */
u32 bus_reset; /* Device is bus resetting */
u32 resume_state; /* USB state to resume */
+ u32 last_state; /* previous USB state */
u32 usb_state; /* USB current state */
u32 ep0_state; /* Endpoint zero state */
u32 ep0_dir; /* Endpoint zero direction: can be