diff options
author | Suresh Mangipudi <smangipudi@nvidia.com> | 2011-08-01 15:34:05 +0530 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2011-11-30 21:47:59 -0800 |
commit | 27f0f234d2416b52a5d1d5db40e6caa43c25bd90 (patch) | |
tree | 2130468c4fa619579a042aa453e0a2b72d1c9e7e /drivers/usb/gadget | |
parent | 73b36a570d4b92c5214d2e30c0f19a928aa24723 (diff) |
usb: otg: tegra: Fix for kernel freeze during resume
Delaying the otg resume to occur after resuming all the devices.
This will make sure all the storage drivers are resumed before
un-register of the host controller driver.
Bug 843287
Reviewed-on: http://git-master/r/42412
(cherry picked from commit a60b2ef0800ba3bebcc6908d3c471d7b0e97423f)
Original-Change-Id: I4912872e03fbd05ac6cd4a7b7a9c7401dc05e480
Reviewed-on: http://git-master/r/44314
Reviewed-by: Varun Colbert <vcolbert@nvidia.com>
Tested-by: Varun Colbert <vcolbert@nvidia.com>
Rebase-Id: Rd0abb04da12a158dad74bd6a2cfb8c734a91fab7
Diffstat (limited to 'drivers/usb/gadget')
-rw-r--r-- | drivers/usb/gadget/fsl_udc_core.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 2a4e4c2436e6..44a253e99d3b 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -3139,42 +3139,45 @@ static int fsl_udc_suspend(struct platform_device *pdev, pm_message_t state) *-----------------------------------------------------------------*/ static int fsl_udc_resume(struct platform_device *pdev) { - if (udc_controller->transceiver) { - if (!(fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_ID_PIN_STATUS)) { - /* If ID status is low means host is connected, return */ - return 0; - } - /* check for VBUS */ - if (!(fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_VBUS_STATUS)) { - /* if there is no VBUS then power down the clocks and return */ - return 0; - } else { + if (udc_controller->transceiver) { + + if (!(fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_ID_PIN_STATUS)) { + /* If ID status is low means host is connected, return */ + return 0; + } + /* check for VBUS */ + if (!(fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_VBUS_STATUS)) { + /* if there is no VBUS then power down the clocks and return */ + return 0; + } else { + if (udc_controller->transceiver->state == OTG_STATE_A_HOST) + return 0; + fsl_udc_clk_resume(true); + /* Detected VBUS set the transceiver state to device mode */ + udc_controller->transceiver->state = OTG_STATE_B_PERIPHERAL; + } + } else { + /* enable the clocks to the controller */ fsl_udc_clk_resume(true); - /* Detected VBUS set the transceiver state to device mode */ - udc_controller->transceiver->state = OTG_STATE_B_PERIPHERAL; - } - } else { - /* enable the clocks to the controller */ - fsl_udc_clk_resume(true); - } + } #if defined(CONFIG_ARCH_TEGRA) - fsl_udc_restart(udc_controller); + fsl_udc_restart(udc_controller); #else - /* Enable DR irq reg and set controller Run */ - if (udc_controller->stopped) { - dr_controller_setup(udc_controller); - dr_controller_run(udc_controller); - } - udc_controller->usb_state = USB_STATE_ATTACHED; - udc_controller->ep0_state = WAIT_FOR_SETUP; - udc_controller->ep0_dir = 0; + /* Enable DR irq reg and set controller Run */ + if (udc_controller->stopped) { + dr_controller_setup(udc_controller); + dr_controller_run(udc_controller); + } + udc_controller->usb_state = USB_STATE_ATTACHED; + udc_controller->ep0_state = WAIT_FOR_SETUP; + udc_controller->ep0_dir = 0; #endif - /* Power down the phy if cable is not connected */ - if (!(fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_VBUS_STATUS)) - fsl_udc_clk_suspend(false); + /* Power down the phy if cable is not connected */ + if (!(fsl_readl(&usb_sys_regs->vbus_wakeup) & USB_SYS_VBUS_STATUS)) + fsl_udc_clk_suspend(false); - return 0; + return 0; } static int fsl_udc_otg_suspend(struct device *dev, pm_message_t state) |