usb: bc: fix usb charger type detect error in rapidly hotplug
authorlyz <lyz@rock-chips.com>
Thu, 21 May 2015 02:15:00 +0000 (10:15 +0800)
committerlyz <lyz@rock-chips.com>
Thu, 11 Jun 2015 06:02:58 +0000 (14:02 +0800)
case for inno phy

In device mode, when doing usb plug and unplug rapidly, there
might be some problem with usb battery charger type detect,
caused by line bounces and other connect problems, at this case,
usb battery charger detect module prefer to report a battery
cherger type that draw less current to make it saver for PMIC and
downstream port safer.

Signed-off-by: lyz <lyz@rock-chips.com>
drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c
drivers/usb/dwc_otg_310/usbdev_bc.c

index 99b3dd7c35efc463cb4cfc502d19e9b1e2f252e2..e5f1c6d201d48a2f1680be3fc85d71eaed2bb126 100755 (executable)
@@ -1637,7 +1637,7 @@ static void dwc_otg_pcd_check_vbus_work(struct work_struct *work)
                        _pcd->conn_status++;
                        if (pldata->bc_detect_cb != NULL) {
                                pldata->bc_detect_cb(_pcd->vbus_status =
-                                                    USB_BC_TYPE_DCP);
+                                                    usb_battery_charger_detect(1));
                        } else {
                                _pcd->vbus_status = USB_BC_TYPE_DCP;
                        }
index 648bd9349a480d935f17e21105a669bba3394a13..3d99f8fbd05295f98d20cd32e8460822efb092c1 100755 (executable)
@@ -210,7 +210,7 @@ enum bc_port_type usb_battery_charger_detect_inno(bool wait)
 {
        enum bc_port_type port_type = USB_BC_TYPE_DISCNT;
        int dcd_state = DCD_POSITIVE;
-       int timeout = 0, i = 0;
+       int timeout = 0, i = 0, filted_cpdet = 0;
 
        /* VBUS Valid detect */
        if (BC_GET(INNO_BC_BVALID) &&
@@ -248,8 +248,22 @@ enum bc_port_type usb_battery_charger_detect_inno(bool wait)
                BC_SET(INNO_BC_IDMSINKEN, 1);
                udelay(T_BC_CHGDET_VALID);
 
+               /*
+                * Filter for Primary Detection,
+                * double check CPDET field
+                */
+               timeout = T_BC_CHGDET_VALID;
+               while(timeout--) {
+                       /*
+                        * In rapidly hotplug case, it's more likely to
+                        * distinguish SDP as DCP/CDP because of line
+                        * bounce
+                        */
+                       filted_cpdet += (BC_GET(INNO_BC_CPDET) ? 1 : -2);
+                       udelay(1);
+               }
                /* SDP and CDP/DCP distinguish */
-               if (BC_GET(INNO_BC_CPDET)) {
+               if (filted_cpdet > 0) {
                        /* Turn off VDPSRC */
                        BC_SET(INNO_BC_VDPSRCEN, 0);
                        BC_SET(INNO_BC_IDMSINKEN, 0);