summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c16
-rw-r--r--drivers/usb/gadget/fsl_usb2_udc.h1
2 files changed, 17 insertions, 0 deletions
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index a26ab58..403f891 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -1785,6 +1785,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;
@@ -2692,6 +2693,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/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index c6703bb..53f508a 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -500,6 +500,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