diff options
author | Peter Chen <peter.chen@freescale.com> | 2011-08-11 17:17:29 +0800 |
---|---|---|
committer | Peter Chen <peter.chen@freescale.com> | 2011-08-17 16:54:14 +0800 |
commit | 29c4a238b447957ebe2a40082f00ef36897f36a6 (patch) | |
tree | 545654ca7251a9349971ed37428a3fbd0d7793a4 /drivers | |
parent | 52660b68b23fe00b98e4ef461f90b6cfff1459a1 (diff) |
ENGR00154044 usb-otg: the device is invalid when usb device at otg port
Below bugs are fixes:
- the device is invalid when usb device at otg port
The reason is udc->suspended is incorrect when otg as host mode
during boot up
- The disconnect can't be detected if usb is online when booting up
The reason is the vbus interrupt enable is cleared by otg switch work
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/gadget/arcotg_udc.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index ac50e8430a60..fb5e8a83a8bd 100644 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -2305,8 +2305,10 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) } if (udc_controller->transceiver) { - /* Suspend the controller until OTG enable it */ - udc_controller->suspended = 1;/* let the otg resume it */ + if (fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID) + udc_controller->suspended = 1;/* let the otg resume it */ + else + udc_controller->suspended = 0;/* let the otg suspend it */ printk(KERN_DEBUG "Suspend udc for OTG auto detect\n"); dr_wake_up_enable(udc_controller, true); dr_clk_gate(false); @@ -3202,6 +3204,20 @@ static int fsl_udc_resume(struct platform_device *pdev) udc_controller->stopped, udc_controller->suspended); /* Do noop if the udc is already at resume state */ if (udc_controller->suspended == 0) { + u32 temp; + if (udc_controller->stopped) + dr_clk_gate(true); + usb_debounce_id_vbus(); + if (fsl_readl(&dr_regs->otgsc) & OTGSC_STS_USB_ID) { + temp = fsl_readl(&dr_regs->otgsc); + /* if b_session_irq_en is cleared by otg */ + if (!(temp & OTGSC_B_SESSION_VALID_IRQ_EN)) { + temp |= OTGSC_B_SESSION_VALID_IRQ_EN; + fsl_writel(temp, &dr_regs->otgsc); + } + } + if (udc_controller->stopped) + dr_clk_gate(false); mutex_unlock(&udc_resume_mutex); return 0; } |