aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/s3c_udc_otg.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/s3c_udc_otg.c')
-rw-r--r--drivers/usb/gadget/s3c_udc_otg.c66
1 files changed, 63 insertions, 3 deletions
diff --git a/drivers/usb/gadget/s3c_udc_otg.c b/drivers/usb/gadget/s3c_udc_otg.c
index 6703973..a4f33cd 100644
--- a/drivers/usb/gadget/s3c_udc_otg.c
+++ b/drivers/usb/gadget/s3c_udc_otg.c
@@ -218,6 +218,21 @@ udc_proc_read(char *page, char **start, off_t off, int count,
#include "s3c_udc_otg_xfer_dma.c"
/*
+* udc_core_disconnect
+* Ask On Connection - Vzw requirement
+*/
+static void udc_core_disconect(struct s3c_udc *dev)
+{
+ u32 uTemp;
+
+ printk(KERN_DEBUG "usb: %s -dev->softconnect=%d\n",
+ __func__, dev->softconnect);
+ uTemp = __raw_readl(dev->regs + S3C_UDC_OTG_DCTL);
+ uTemp |= SOFT_DISCONNECT;
+ __raw_writel(uTemp, dev->regs + S3C_UDC_OTG_DCTL);
+}
+
+/*
* udc_disable - disable USB device controller
*/
static void udc_disable(struct s3c_udc *dev)
@@ -307,6 +322,18 @@ int s3c_vbus_enable(struct usb_gadget *gadget, int is_active)
{
unsigned long flags;
struct s3c_udc *dev = container_of(gadget, struct s3c_udc, gadget);
+ mutex_lock(&dev->mutex);
+
+ if (dev->is_usb_ready) {
+ printk(KERN_DEBUG "usb: %s, ready u_e: %d, is_active: %d\n",
+ __func__, dev->udc_enabled, is_active);
+ } else { /* USB is not ready to enable USB PHY */
+ printk(KERN_DEBUG "usb: %s, not ready u_e: %d, is_active: %d\n",
+ __func__, dev->udc_enabled, is_active);
+ dev->udc_enabled = is_active;
+ mutex_unlock(&dev->mutex);
+ return 0;
+ }
if (dev->udc_enabled != is_active) {
dev->udc_enabled = is_active;
@@ -324,11 +351,14 @@ int s3c_vbus_enable(struct usb_gadget *gadget, int is_active)
wake_lock_timeout(&dev->usbd_wake_lock, HZ * 5);
wake_lock_timeout(&dev->usb_cb_wake_lock, HZ * 5);
} else {
- printk(KERN_DEBUG "usb: %s is_active=%d(udc_enable)\n",
- __func__, is_active);
+ printk(KERN_DEBUG "usb: %s is_active=%d(udc_enable),"
+ "softconnect=%d\n",
+ __func__, is_active, dev->softconnect);
wake_lock(&dev->usb_cb_wake_lock);
udc_reinit(dev);
udc_enable(dev);
+ if (!dev->softconnect)
+ udc_core_disconect(dev);
}
} else {
printk(KERN_DEBUG "usb: %s, udc_enabled : %d, is_active : %d\n",
@@ -336,7 +366,7 @@ int s3c_vbus_enable(struct usb_gadget *gadget, int is_active)
}
-
+ mutex_unlock(&dev->mutex);
return 0;
}
@@ -894,6 +924,9 @@ static void s3c_udc_soft_disconnect(void)
static int s3c_udc_pullup(struct usb_gadget *gadget, int is_on)
{
+ struct s3c_udc *dev = container_of(gadget, struct s3c_udc, gadget);
+ dev->softconnect = is_on;
+
if (is_on)
s3c_udc_soft_connect();
else
@@ -1157,6 +1190,27 @@ static struct s3c_udc memory = {
},
};
+static void usb_ready(struct work_struct *work)
+{
+ struct s3c_udc *dev =
+ container_of(work, struct s3c_udc, usb_ready_work.work);
+
+ if (!dev) {
+ printk(KERN_DEBUG "usb: %s dev is NULL\n", __func__);
+ return ;
+ }
+
+ printk(KERN_DEBUG "usb: %s udc_enable=%d\n",
+ __func__, dev->udc_enabled);
+
+ dev->is_usb_ready = true;
+
+ if (dev->udc_enabled) {
+ dev->udc_enabled = 0;
+ s3c_vbus_enable(&dev->gadget, 1);
+ }
+}
+
/*
* probe - binds to the platform device
*/
@@ -1262,6 +1316,10 @@ static int s3c_udc_probe(struct platform_device *pdev)
create_proc_files();
+ INIT_DELAYED_WORK(&dev->usb_ready_work, usb_ready);
+ schedule_delayed_work(&dev->usb_ready_work, msecs_to_jiffies(15000));
+ mutex_init(&dev->mutex);
+
return retval;
err_clk:
clk_put(dev->clk);
@@ -1298,6 +1356,8 @@ static int s3c_udc_remove(struct platform_device *pdev)
the_controller = 0;
wake_lock_destroy(&dev->usbd_wake_lock);
wake_lock_destroy(&dev->usb_cb_wake_lock);
+ cancel_delayed_work(&dev->usb_ready_work);
+ mutex_destroy(&dev->mutex);
return 0;
}