diff options
author | Peter Chen <peter.chen@freescale.com> | 2012-06-11 14:31:20 +0800 |
---|---|---|
committer | Jason Liu <r64343@freescale.com> | 2012-07-20 13:38:36 +0800 |
commit | 7ded0ecccf2c54dc8e92510ce49028f0e85a01ba (patch) | |
tree | f9840f8a83642e3efb4b896a205563b79aa2294f /drivers/usb | |
parent | 5165102fd3131376c5527344c47e4946d91bf0bb (diff) |
ENGR00212992 usb: fix potential bug with fast plug in/out with usb charger
- Move imx_usb_vbus_disconnect to work queue, and wait or cancel
charger detect worker when vbus is disconnected if charger detect
worker still hasn't finished.
- Move pull down dp from imx_usb_vbus_disconnect to udc vbus
disconnect interrupt handler, the reason is udc->gadget.speed should
to be updated at that ISR.
- Select POWER_SUPPLY if USB_GADGET_ARC is configured to fix the build
error for manufacture tools firmware's build.
Signed-off-by: Peter Chen <peter.chen@freescale.com>
Diffstat (limited to 'drivers/usb')
-rwxr-xr-x | drivers/usb/gadget/Kconfig | 1 | ||||
-rwxr-xr-x | drivers/usb/gadget/arcotg_udc.c | 13 | ||||
-rw-r--r-- | drivers/usb/gadget/imx_usb_charger.c | 8 |
3 files changed, 12 insertions, 10 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 43006e49d903..085c709bc65f 100755 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -159,6 +159,7 @@ config USB_GADGET_ARC depends on ARCH_MXC || ARCH_STMP3XXX || ARCH_MXS select USB_GADGET_DUALSPEED select USB_OTG_UTILS + select POWER_SUPPLY help Some Freescale processors have a USBOTG controller, which supports device mode. diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c index 8def72278d19..90eb9864b0a8 100755 --- a/drivers/usb/gadget/arcotg_udc.c +++ b/drivers/usb/gadget/arcotg_udc.c @@ -491,7 +491,6 @@ static void dr_controller_run(struct fsl_udc *udc) if (!(temp & OTGSC_B_SESSION_VALID)) { /* Set stopped before low power mode */ udc->vbus_active = false; - imx_usb_vbus_disconnect(&udc->charger); /* charger disconnect */ udc->stopped = 1; /* enable wake up */ dr_wake_up_enable(udc, true); @@ -513,7 +512,8 @@ static void dr_controller_run(struct fsl_udc *udc) /* disable pulldown dp and dm */ dr_discharge_line(udc->pdata, false); udc->vbus_active = true; - imx_usb_vbus_connect(&udc->charger); /* charger detect */ + /* notify vbus is connected */ + imx_usb_vbus_connect(&udc->charger); printk(KERN_DEBUG "%s: udc out low power mode\n", __func__); } @@ -2182,9 +2182,10 @@ static void fsl_gadget_disconnect_event(struct work_struct *work) pdata = udc->pdata; + /* notify vbus is disconnected */ + imx_usb_vbus_disconnect(&udc->charger); /* wait line to se0 */ dr_discharge_line(pdata, true); - /* * Wait class drivers finish, an well-behaviour class driver should * call ep_disable when it is notified to be disconnected. @@ -2242,11 +2243,12 @@ bool try_wake_up_udc(struct fsl_udc *udc) udc->stopped = 0; /* disable pulldown dp and dm */ dr_discharge_line(pdata, false); - imx_usb_vbus_connect(&udc->charger); /* charger detect */ + /* notify vbus is connected */ + imx_usb_vbus_connect(&udc->charger); printk(KERN_DEBUG "%s: udc out low power mode\n", __func__); } else { udc->vbus_active = false; - imx_usb_vbus_disconnect(&udc->charger); /* charger disconnect */ + fsl_pullup(&udc_controller->gadget, false); /* usbcmd.rs=0 */ /* here we need disable B_SESSION_IRQ, after * schedule_work finished, it need to be enabled again. * Doing like this can avoid conflicting between rapid @@ -2257,7 +2259,6 @@ bool try_wake_up_udc(struct fsl_udc *udc) fsl_writel(tmp & (~OTGSC_B_SESSION_VALID_IRQ_EN), &dr_regs->otgsc); - /* update port status */ fsl_udc_speed_update(udc); spin_unlock(&udc->lock); diff --git a/drivers/usb/gadget/imx_usb_charger.c b/drivers/usb/gadget/imx_usb_charger.c index 41043b432102..e1020421adb8 100644 --- a/drivers/usb/gadget/imx_usb_charger.c +++ b/drivers/usb/gadget/imx_usb_charger.c @@ -178,7 +178,7 @@ static int usb_charger_detect(struct usb_charger *charger) return 1; } -void usb_charger_init(struct usb_charger *charger) +static void usb_charger_init(struct usb_charger *charger) { charger->bc = BATTERY_CHARGING_SPEC_1_2; charger->detect = usb_charger_detect; @@ -298,12 +298,12 @@ EXPORT_SYMBOL(imx_usb_vbus_connect); */ int imx_usb_vbus_disconnect(struct usb_charger *charger) { - if (charger->dp_pullup) - charger->dp_pullup(false); /* usbcmd.rs = 0 */ - if (!charger->enable) return 0; + /* in case, the charger detect is doing or pending */ + cancel_work_sync(&charger->work); + charger->online = 0; charger->present = 0; charger->max_current = 0; |