usb: bc: implement DCD phase
authorlyz <lyz@rock-chips.com>
Tue, 1 Apr 2014 09:05:27 +0000 (17:05 +0800)
committerlyz <lyz@rock-chips.com>
Tue, 1 Apr 2014 09:07:45 +0000 (17:07 +0800)
drivers/usb/dwc_otg_310/usbdev_bc.c
drivers/usb/dwc_otg_310/usbdev_bc.h

index d108867fa4218e1ae9c9a1bafab2156b2eac8480..ced7cb4b1ae39dee98304850bc00c0ca89974433 100755 (executable)
@@ -65,6 +65,8 @@ inline static void uoc_init_synop(struct device_node *np)
     uoc_init_field(np, "rk_usb,vdatdetenb", &pBC_UOC_FIELDS[SYNOP_BC_VDATDETENB]);
     uoc_init_field(np, "rk_usb,chrgsel",  &pBC_UOC_FIELDS[SYNOP_BC_CHRGSEL]);
     uoc_init_field(np, "rk_usb,chgdet",   &pBC_UOC_FIELDS[SYNOP_BC_CHGDET]);
+    uoc_init_field(np, "rk_usb,fsvplus",  &pBC_UOC_FIELDS[SYNOP_BC_FSVPLUS]);
+    uoc_init_field(np, "rk_usb,fsvminus", &pBC_UOC_FIELDS[SYNOP_BC_FSVMINUS]);
 }
 
 inline static void uoc_init_rk(struct device_node *np)
@@ -132,62 +134,75 @@ int usb_battery_charger_detect_inno(bool wait)
 //wait wait for dcd timeout 900ms
 int usb_battery_charger_detect_synop(bool wait)
 {
-    int port_type = USB_BC_TYPE_DISCNT;
-    int timeout;
-    //VBUS Valid detect
-
-    if(BC_GET(SYNOP_BC_BVALID)) {
-        //todo : add DCD !
-        mdelay(wait ? T_DCD_TIMEOUT : 1);
-
-        /* Turn on VDPSRC */
-        //Primary Detection
-        BC_SET(SYNOP_BC_VDATSRCENB, 1);
-        BC_SET(SYNOP_BC_VDATDETENB, 1);
-        BC_SET(SYNOP_BC_CHRGSEL, 0);
-
-        timeout = wait ? T_BC_WAIT_CHGDET : 1;
-        while(timeout--) {
-            if(BC_GET(SYNOP_BC_CHGDET))
-                break;
-            mdelay(1);
-        }
-
-        /* SDP and CDP/DCP distinguish */
-        if(BC_GET(SYNOP_BC_CHGDET)) {
-            /* Turn off VDPSRC */
-            BC_SET(SYNOP_BC_VDATSRCENB, 0);
-            BC_SET(SYNOP_BC_VDATDETENB, 0);
-
-            timeout = wait ? T_BC_SRC_OFF : 1;
-            while(timeout--) {
-                if(!BC_GET(SYNOP_BC_CHGDET))
-                    break;
-                mdelay(1);
-            };
-
-            /* Turn on VDMSRC */
-            BC_SET(SYNOP_BC_VDATSRCENB, 1);
-            BC_SET(SYNOP_BC_VDATDETENB, 1);
-            BC_SET(SYNOP_BC_CHRGSEL, 1);
-            udelay(200);
-            if(BC_GET(SYNOP_BC_CHGDET))
-                port_type = USB_BC_TYPE_DCP;
-            else
-                port_type = USB_BC_TYPE_CDP;
-        } else {
-            port_type = USB_BC_TYPE_SDP;
-        }
-        BC_SET(SYNOP_BC_VDATSRCENB, 0);
-        BC_SET(SYNOP_BC_VDATDETENB, 0);
-        BC_SET(SYNOP_BC_CHRGSEL, 0);
-
-    }
-
-    printk("%s , battery_charger_detect %d\n", __func__, port_type);
-    return port_type;
+       int port_type = USB_BC_TYPE_DISCNT;
+       int dcd_state;
+       int timeout = 0, i = 0;
+       //VBUS Valid detect
+       if(BC_GET(SYNOP_BC_BVALID)) {
+               if(wait) {
+                       //Do DCD
+                       dcd_state = DCD_TIMEOUT;
+                       BC_SET(SYNOP_BC_DCDENB, 1);
+                       timeout = T_DCD_TIMEOUT;
+                       while(timeout--) {
+                               if(!BC_GET(SYNOP_BC_FSVPLUS))
+                                       i++;
+                               if(i >= 3) {//It is a filter here to assure data lines contacted for at least 3ms
+                                       dcd_state = DCD_POSITIVE;
+                                       break;
+                               }
+
+                               mdelay(1);
+                       }
+                       BC_SET(SYNOP_BC_DCDENB, 0);
+               } else{
+                       dcd_state = DCD_PASSED;
+               }
+               if(dcd_state == DCD_TIMEOUT){
+                       port_type = USB_BC_TYPE_UNKNOW;
+                       goto out;
+               }
+
+               /* Turn on VDPSRC */
+               //Primary Detection
+               BC_SET(SYNOP_BC_VDATSRCENB, 1);
+               BC_SET(SYNOP_BC_VDATDETENB, 1);
+               BC_SET(SYNOP_BC_CHRGSEL, 0);
+               
+               udelay(T_BC_CHGDET_VALID);
+               
+               /* SDP and CDP/DCP distinguish */
+               if(BC_GET(SYNOP_BC_CHGDET)) {
+                       /* Turn off VDPSRC */
+                       BC_SET(SYNOP_BC_VDATSRCENB, 0);
+                       BC_SET(SYNOP_BC_VDATDETENB, 0);
+
+                       udelay(T_BC_CHGDET_VALID);
+
+                       /* Turn on VDMSRC */
+                       BC_SET(SYNOP_BC_VDATSRCENB, 1);
+                       BC_SET(SYNOP_BC_VDATDETENB, 1);
+                       BC_SET(SYNOP_BC_CHRGSEL, 1);
+                       udelay(T_BC_CHGDET_VALID);
+                       if(BC_GET(SYNOP_BC_CHGDET))
+                               port_type = USB_BC_TYPE_DCP;
+                       else
+                               port_type = USB_BC_TYPE_CDP;
+               } else {
+                       port_type = USB_BC_TYPE_SDP;
+               }
+               BC_SET(SYNOP_BC_VDATSRCENB, 0);
+               BC_SET(SYNOP_BC_VDATDETENB, 0);
+               BC_SET(SYNOP_BC_CHRGSEL, 0);
+
+       }
+out:
+       printk("%s , battery_charger_detect %d, %s DCD, dcd_state = %d\n",
+               __func__, port_type, wait ? "wait" : "pass", dcd_state);
+       return port_type;
 }
 
+
 int usb_battery_charger_detect(bool wait)
 {
     static struct device_node *np = NULL;
index 88d714e5019c46d90aaec926d7edebe38675bd33..7e6b9bdf41e9d5d0a686619b1eb96c8565162280 100644 (file)
@@ -15,6 +15,8 @@ enum {
     SYNOP_BC_VDATDETENB,
     SYNOP_BC_CHRGSEL,
     SYNOP_BC_CHGDET,
+    SYNOP_BC_FSVPLUS,
+    SYNOP_BC_FSVMINUS,
     SYNOP_BC_MAX,      
 };
 
@@ -28,10 +30,15 @@ enum {
     RK_BC_MAX,
 };
 
-#define T_DCD_TIMEOUT   (200)
+#define T_DCD_TIMEOUT   (400)
 #define T_BC_WAIT_CHGDET (40)
-#define T_BC_SRC_OFF     (10)
+#define T_BC_CHGDET_VALID (200)
 
+enum {
+       DCD_POSITIVE = 0,
+       DCD_PASSED,
+       DCD_TIMEOUT,
+};
 
 /***********************************
 USB Port Type