reconnect to PC if usb config change
authoryangkai <yangkai@ubuntu-fs>
Thu, 5 May 2011 08:57:23 +0000 (16:57 +0800)
committeryangkai <yangkai@ubuntu-fs>
Thu, 5 May 2011 08:57:23 +0000 (16:57 +0800)
drivers/usb/dwc_otg/dwc_otg_pcd.c
drivers/usb/gadget/composite.c [changed mode: 0644->0755]

index 6c1f1d720c18be338b38d3a995d1551209eaa47f..4df9ff25b86c03c2b0a40be4e1f7d18751bcd42b 100755 (executable)
@@ -567,8 +567,8 @@ static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep,
                 ep = container_of(_ep, dwc_otg_pcd_ep_t, ep);
                 request_done(ep, req, -ECONNABORTED);
         DWC_PRINT("%s::ep %s req not empty,done it error!\n" , __func__, _ep->name);
-               return -EINVAL;
         }
+               return -EINVAL;
        }
        
        ep = container_of(_ep, dwc_otg_pcd_ep_t, ep);
@@ -999,10 +999,42 @@ static int dwc_otg_pcd_wakeup(struct usb_gadget *_gadget)
        return 0;
 }
 
+static int dwc_otg_pcd_pullup(struct usb_gadget *_gadget, int is_on)
+{
+       unsigned long flags;
+       dwc_otg_pcd_t *pcd;
+    dctl_data_t dctl = {.d32=0};
+    dwc_otg_core_if_t *core_if;
+       DWC_DEBUGPL(DBG_PCDV,"%s(%p)\n", __func__, _gadget);
+               
+       if (_gadget == 0)
+       {
+               return -ENODEV;
+       } 
+       else 
+       {
+               pcd = container_of(_gadget, dwc_otg_pcd_t, gadget);
+        core_if = GET_CORE_IF(pcd); 
+       }
+       if(is_on)   //connect
+       {
+        dctl.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dctl );
+        dctl.b.sftdiscon = 0;
+        dwc_write_reg32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
+    }
+    else        //disconnect
+    {
+        dctl.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dctl );
+        dctl.b.sftdiscon = 1;
+        dwc_write_reg32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
+    }
+}
+
 static const struct usb_gadget_ops dwc_otg_pcd_ops = 
 {
        .get_frame       = dwc_otg_pcd_get_frame,
        .wakeup          = dwc_otg_pcd_wakeup,
+       .pullup      = dwc_otg_pcd_pullup,
        // current versions must always be self-powered
 };
 
@@ -1619,7 +1651,6 @@ static void dwc_phy_reconnect(struct work_struct *work)
     core_if = GET_CORE_IF(pcd); 
     gctrl.d32 = dwc_read_reg32( &core_if->core_global_regs->gotgctl );
     if( gctrl.b.bsesvld  ) {
-        dwc_otg_msc_lock(pcd);
         pcd->conn_status++;
            dwc_pcd_reset(pcd);
        /*
@@ -1649,24 +1680,25 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
     if( gctrl.b.bsesvld ) {
         /* if usb not connect before ,then start connect */
          if( _pcd->vbus_status == 0 ) {
+            dwc_otg_msc_lock(_pcd);
             DWC_PRINT("********vbus detect*********************************************\n");
-           _pcd->vbus_status = 1;
-        /* soft disconnect */
-        dctl.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dctl );
-        dctl.b.sftdiscon = 1;
-        dwc_write_reg32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
-        /* Clear any pending interrupts */
-        dwc_write_reg32( &core_if->core_global_regs->gintsts, 0xFFFFFFFF); 
-        if(_pcd->conn_en)
-           {
-           schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
-                    _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
-           }
+           _pcd->vbus_status = 1;
+            /* soft disconnect */
+            dctl.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dctl );
+            dctl.b.sftdiscon = 1;
+            dwc_write_reg32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
+            /* Clear any pending interrupts */
+            dwc_write_reg32( &core_if->core_global_regs->gintsts, 0xFFFFFFFF); 
+            if(_pcd->conn_en)
+           {
+                   schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
+                    _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
+           }
 
         } else if((_pcd->conn_status>0)&&(_pcd->conn_status <3)) {
-            dwc_otg_msc_unlock(_pcd);
+            //dwc_otg_msc_unlock(_pcd);
             DWC_PRINT("********soft reconnect******************************************\n");
-            _pcd->vbus_status =0;
+            //_pcd->vbus_status =0;
             
             /* soft disconnect */
                dctl.d32 = dwc_read_reg32( &core_if->dev_if->dev_global_regs->dctl );
@@ -1674,6 +1706,11 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long pdata )
                dwc_write_reg32( &core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
             /* Clear any pending interrupts */
             dwc_write_reg32( &core_if->core_global_regs->gintsts, 0xFFFFFFFF); 
+            if(_pcd->conn_en)
+           {
+                   schedule_delayed_work( &_pcd->reconnect , 8 ); /* delay 1 jiffies */
+                    _pcd->check_vbus_timer.expires = jiffies + (HZ<<1); /* 1 s */
+           }
         }
         else if((_pcd->conn_en)&&(_pcd->conn_status == 0))
         {
@@ -1722,7 +1759,7 @@ void dwc_otg_pcd_start_vbus_timer( dwc_otg_pcd_t * _pcd )
          * when receive reset int,the vbus state may not be update,so 
          * always start timer here.
          */                
-        mod_timer( vbus_timer , jiffies + (HZ<<2));
+        mod_timer( vbus_timer , jiffies + (HZ));
 }
 
 /*
old mode 100644 (file)
new mode 100755 (executable)
index c6ab4d1..140fafe
@@ -113,7 +113,7 @@ void usb_composite_force_reset(struct usb_composite_dev *cdev)
        if (cdev && cdev->gadget &&
                        cdev->gadget->speed != USB_SPEED_UNKNOWN) {
                /* avoid sending a disconnect switch event until after we disconnect */
-               cdev->mute_switch = 1;
+//             cdev->mute_switch = 1;// yk 20110505 rk29 don't need to mute switch
                spin_unlock_irqrestore(&cdev->lock, flags);
 
                usb_gadget_disconnect(cdev->gadget);