summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinyu Chen <b03824@freescale.com>2011-12-07 13:32:03 +0800
committerXinyu Chen <b03824@freescale.com>2011-12-07 13:50:19 +0800
commitd6720614e43bd2f9cc7619709ad562195867f039 (patch)
treecb742e1c8713543da60902ef8ee148181bf6a6ce
parent060080192460ce7c46b1cc6d7535ddfc76d5ea67 (diff)
ENGR00169660 android usb: unstable on function en/disable and plug/unplug
This commit revert the previous workaround for hang issue when usb is not connected and clock gated. And fix the following issues: * kernel hang when boot without usb cable connected If the usb is not connected and clock gated, do not call usb_gadget_connect() until usb connected. * Android usb manager can not get correct status from driver on boot. Android gadget enabled on boot after usb connected, and so miss the USB_REQ_SET_CONFIGURATION request. Need a reconnect for gadget on gadget enable. * Enable/disable ADB by UI causes system hang or not functionable Only when there's a connection, we call usb_gadget_disconnect() when disable android gadget. When enable gadget, do reconnect. Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
-rw-r--r--drivers/usb/gadget/android.c20
-rw-r--r--drivers/usb/gadget/arcotg_udc.c10
2 files changed, 18 insertions, 12 deletions
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 98c2f04225d0..d91a0ed4d426 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -822,6 +822,7 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
struct android_dev *dev = dev_get_drvdata(pdev);
struct usb_composite_dev *cdev = dev->cdev;
int enabled = 0;
+ unsigned long flags;
sscanf(buff, "%d", &enabled);
if (enabled && !dev->enabled) {
@@ -835,12 +836,23 @@ static ssize_t enable_store(struct device *pdev, struct device_attribute *attr,
cdev->desc.bDeviceProtocol = device_desc.bDeviceProtocol;
usb_add_config(cdev, &android_config_driver,
android_bind_config);
- usb_gadget_connect(cdev->gadget);
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (dev->connected) {
+ usb_gadget_disconnect(cdev->gadget);
+ mdelay(10);
+ usb_gadget_connect(cdev->gadget);
+ usb_gadget_vbus_connect(cdev->gadget);
+ }
+ spin_unlock_irqrestore(&cdev->lock, flags);
dev->enabled = true;
} else if (!enabled && dev->enabled) {
- usb_gadget_disconnect(cdev->gadget);
- /* Cancel pending control requests */
- usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
+ spin_lock_irqsave(&cdev->lock, flags);
+ if (dev->connected) {
+ /* Cancel pending control requests */
+ usb_gadget_disconnect(cdev->gadget);
+ usb_ep_dequeue(cdev->gadget->ep0, cdev->req);
+ }
+ spin_unlock_irqrestore(&cdev->lock, flags);
usb_remove_config(cdev, &android_config_driver);
dev->enabled = false;
} else {
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index e84ede66ad9c..391ba5820527 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -1431,18 +1431,12 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on)
udc = container_of(gadget, struct fsl_udc, gadget);
udc->softconnect = (is_on != 0);
- dr_clk_gate(true);
- if (can_pullup(udc)) {
+ if (can_pullup(udc))
fsl_writel((fsl_readl(&dr_regs->usbcmd) | USB_CMD_RUN_STOP),
&dr_regs->usbcmd);
- dr_phy_low_power_mode(udc, false);
- } else {
+ else
fsl_writel((fsl_readl(&dr_regs->usbcmd) & ~USB_CMD_RUN_STOP),
&dr_regs->usbcmd);
- dr_wake_up_enable(udc, true);
- dr_phy_low_power_mode(udc, true);
- }
- dr_clk_gate(false);
return 0;
}