From d6720614e43bd2f9cc7619709ad562195867f039 Mon Sep 17 00:00:00 2001 From: Xinyu Chen Date: Wed, 7 Dec 2011 13:32:03 +0800 Subject: 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 --- drivers/usb/gadget/android.c | 20 ++++++++++++++++---- drivers/usb/gadget/arcotg_udc.c | 10 ++-------- 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; } -- cgit v1.2.3