hidg: support boot protocol
[firefly-linux-kernel-4.4.55.git] / drivers / usb / dwc_otg / dwc_otg_pcd.c
index 25dfd65c35e07f273bca82d65e0e0a31cfc6d55d..50ec2d87860509fbae80633c766faedea2442d18 100755 (executable)
@@ -568,11 +568,9 @@ static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep,
        /* 20091226,HSL@RK */
        if ( !list_empty(&req->queue) ) 
        {
-        while(!list_empty(&req->queue) ) {
-                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);
-        }
+               list_del_init(&req->queue);
+               ep = container_of(_ep, dwc_otg_pcd_ep_t, ep);
+               DWC_PRINT("%s::ep %s req not empty,done it error!\n" , __func__, _ep->name);
                return -EINVAL;
        }
        
@@ -649,6 +647,10 @@ static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep,
                                DWC_DEBUGPL(DBG_PCD, 
                                                                "%s ep0: EP0_IN_DATA_PHASE\n", 
                                                                __func__);
+                           if((_req->length % MAX_EP0_SIZE) == 0){
+                               if(_req->zero)
+                                   ep->dwc_ep.sent_zlp = 1;
+                               }
                                break;
 
                        case EP0_OUT_DATA_PHASE:
@@ -662,7 +664,13 @@ static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep,
                                        pcd->ep0state = EP0_STATUS;
                                }
                                break;
-                                               
+                               
+                       case EP0_STATUS:
+                               DWC_DEBUGPL(DBG_PCD,
+                                           "%s ep0: EP0_IN_STATUS_PHASE\n",
+                                           __func__);
+                               break;
+                               
                        default:
                                DWC_DEBUGPL(DBG_ANY, "ep0: odd state %d\n", 
                                                                                        pcd->ep0state);
@@ -675,7 +683,6 @@ static int dwc_otg_pcd_ep_queue(struct usb_ep *_ep,
                        ep->dwc_ep.xfer_buff = _req->buf;
                        ep->dwc_ep.xfer_len = _req->length;
                        ep->dwc_ep.xfer_count = 0;
-                       ep->dwc_ep.sent_zlp = 0;
                        ep->dwc_ep.total_len = ep->dwc_ep.xfer_len;
                        dwc_otg_ep0_start_transfer( GET_CORE_IF(pcd), 
                                                                                &ep->dwc_ep );
@@ -1590,7 +1597,6 @@ int dwc_pcd_reset(dwc_otg_pcd_t *pcd)
 {
     dwc_otg_core_if_t *core_if = GET_CORE_IF(pcd);
     dwc_otg_disable_global_interrupts( core_if );
-    //
 #ifdef CONFIG_ARCH_RK29
     cru_set_soft_reset(SOFT_RST_USB_OTG_2_0_AHB_BUS, true);
     cru_set_soft_reset(SOFT_RST_USB_OTG_2_0_PHY, true);
@@ -1762,34 +1768,44 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long data )
        dwc_otg_device_t *otg_dev = (dwc_otg_device_t *)(*((uint32_t *)_dev->platform_data));
     dwc_otg_pcd_t * _pcd = otg_dev->pcd;
     unsigned long flags;
-
-       local_irq_save(flags);
+    local_irq_save(flags);
     _pcd->check_vbus_timer.expires = jiffies + (HZ); /* 1 s */
-    if(!pldata->get_status(USB_STATUS_ID)){  // id low
-        if( pldata->phy_status){ 
+    if(!pldata->get_status(USB_STATUS_ID))
+    {  // id low
+        if( pldata->dwc_otg_uart_mode != NULL )
+        {//exit phy bypass to uart & enable usb phy
+            pldata->dwc_otg_uart_mode( pldata, PHY_USB_MODE);
+        }
+        if( pldata->phy_status)
+        { 
             pldata->clock_enable( pldata, 1);          
             pldata->phy_suspend(pldata, USB_PHY_ENABLED);
         } 
     }
-       else if(pldata->get_status(USB_STATUS_BVABLID)){  // bvalid
+       else if(pldata->get_status(USB_STATUS_BVABLID))
+       {  // bvalid
         /* if usb not connect before ,then start connect */
-         if( _pcd->vbus_status == 0 ) {
+         if( _pcd->vbus_status == 0 ) 
+         {
             DWC_PRINT("********vbus detect*********************************************\n");
            _pcd->vbus_status = 1;
             if(_pcd->conn_en)
                 goto connect;
-            else if( pldata->phy_status == USB_PHY_ENABLED ){
+            else if( pldata->phy_status == USB_PHY_ENABLED )
+            {
                 // not connect, suspend phy
                 pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
                 udelay(3);
                 pldata->clock_enable( pldata, 0);
             }
         } 
-        else if((_pcd->conn_en)&&(_pcd->conn_status>=0)&&(_pcd->conn_status <3)){
+        else if((_pcd->conn_en)&&(_pcd->conn_status>=0)&&(_pcd->conn_status <3))
+        {
             DWC_PRINT("********soft reconnect******************************************\n");
            goto connect;
         }
-        else if(_pcd->conn_status ==3){
+        else if(_pcd->conn_status ==3)
+        {
                        //*Á¬½Ó²»ÉÏʱÊÍ·ÅËø£¬ÔÊÐíϵͳ½øÈë¶þ¼¶Ë¯Ãߣ¬yk@rk,20100331*//
             dwc_otg_msc_unlock(_pcd);
             _pcd->conn_status++;
@@ -1797,24 +1813,33 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long data )
                 _pcd->vbus_status = 2;
                 
             // not connect, suspend phy
-            if( pldata->phy_status == USB_PHY_ENABLED ){
+            if( pldata->phy_status == USB_PHY_ENABLED )
+            {
                 pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
                 udelay(3);
                 pldata->clock_enable( pldata, 0);
             }
         }
-       }else {
+       }
+    else 
+    {
         _pcd->vbus_status = 0;
-        if(_pcd->conn_status){
+        if(_pcd->conn_status)
+        {
              _pcd->conn_status = 0;
-             dwc_otg_msc_unlock(_pcd);
         }
-        else if( pldata->phy_status == USB_PHY_ENABLED ){ 
+        else if( pldata->phy_status == USB_PHY_ENABLED )
+        { 
             /* no vbus detect here , close usb phy  */
             pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
             udelay(3);
-            pldata->clock_enable( pldata, 0);          
-        }
+            pldata->clock_enable( pldata, 0);
+            /* usb phy bypass to uart mode  */
+            if( pldata->dwc_otg_uart_mode != NULL )
+                pldata->dwc_otg_uart_mode( pldata, PHY_UART_MODE);    
+            /* release wake lock */
+            dwc_otg_msc_unlock(_pcd);
+        }  
     }
     add_timer(&_pcd->check_vbus_timer); 
        local_irq_restore(flags);
@@ -1823,7 +1848,8 @@ static void dwc_otg_pcd_check_vbus_timer( unsigned long data )
 connect:
     if(_pcd->conn_status==0)
         dwc_otg_msc_lock(_pcd);
-    if( pldata->phy_status){
+    if( pldata->phy_status)
+    {
         pldata->clock_enable( pldata, 1);      
         pldata->phy_suspend(pldata, USB_PHY_ENABLED);
     }
@@ -1873,7 +1899,8 @@ int dwc_otg_pcd_init(struct device *dev)
        static char pcd_name[] = "dwc_otg_pcd";
        dwc_otg_pcd_t *pcd;
        dwc_otg_device_t *otg_dev = (dwc_otg_device_t *)(*((uint32_t *)dev->platform_data));
-    dwc_otg_core_if_t *core_if = otg_dev->core_if;
+    dwc_otg_core_if_t *core_if = otg_dev->core_if; 
+       struct dwc_otg_platform_data *pldata = dev->platform_data;
        int retval = 0;
        int irq;
         /*
@@ -1970,9 +1997,26 @@ int dwc_otg_pcd_init(struct device *dev)
     
     INIT_DELAYED_WORK(&pcd->reconnect , dwc_phy_reconnect);
     pcd->vbus_status  = 0;
-    pcd->phy_suspend  = 0;
-    if(dwc_otg_is_device_mode(core_if))
-        mod_timer(&pcd->check_vbus_timer, jiffies+(HZ<<4)); // delay 16 S  
+    pcd->phy_suspend  = 0; 
+    if(dwc_otg_is_device_mode(core_if)){
+#ifdef CONFIG_RK_USB_UART        
+        if(pldata->get_status(USB_STATUS_BVABLID))
+        {
+             pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);
+        }//phy usb mode
+        else
+        {
+            pldata->phy_suspend(pldata,USB_PHY_SUSPEND);
+            pldata->dwc_otg_uart_mode(pldata, PHY_UART_MODE);
+        }//phy bypass to uart mode
+#endif
+        mod_timer(&pcd->check_vbus_timer, jiffies+(HZ<<4)); // delay 16 S 
+    }
+#ifdef CONFIG_RK_USB_UART
+    else if(pldata->dwc_otg_uart_mode != NULL)
+        pldata->dwc_otg_uart_mode(pldata, PHY_USB_MODE);//disable phy bypass uart  
+#endif
+
        return 0;
 }
 /**