From 78546c0544fbb283857cf26a42c86fb3f3cd3466 Mon Sep 17 00:00:00 2001
From: wlf <wulf@rock-chips.com>
Date: Sat, 22 Mar 2014 17:53:49 +0800
Subject: [PATCH] USB charger: Fix the bug that cause USB Reset continually.

---
 drivers/usb/dwc_otg_310/dwc_otg_pcd.c       |  2 +-
 drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c | 15 ++++++-----
 drivers/usb/dwc_otg_310/usbdev_bc.c         | 29 ++++++++++++++++++++-
 drivers/usb/dwc_otg_310/usbdev_rk.h         |  2 ++
 drivers/usb/dwc_otg_310/usbdev_rk32.c       | 21 ++++++++++++---
 5 files changed, 57 insertions(+), 12 deletions(-)
 mode change 100644 => 100755 drivers/usb/dwc_otg_310/usbdev_bc.c

diff --git a/drivers/usb/dwc_otg_310/dwc_otg_pcd.c b/drivers/usb/dwc_otg_310/dwc_otg_pcd.c
index 320341b2fe15..a8897cb12758 100755
--- a/drivers/usb/dwc_otg_310/dwc_otg_pcd.c
+++ b/drivers/usb/dwc_otg_310/dwc_otg_pcd.c
@@ -2640,8 +2640,8 @@ void 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);
+	dwc_otg_core_init(core_if);
     dwc_otg_pcd_reinit(pcd);
-    msleep(100);
     dwc_otg_core_dev_init(core_if);
     dwc_otg_enable_global_interrupts(core_if);
 }
diff --git a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c
index 3fac0abb6c11..f763e69b5420 100755
--- a/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c
+++ b/drivers/usb/dwc_otg_310/dwc_otg_pcd_linux.c
@@ -1518,9 +1518,9 @@ static void dwc_otg_pcd_check_vbus_work( struct work_struct *work )
 		/* if usb not connect before ,then start connect */
 		if( _pcd->vbus_status == USB_BC_TYPE_DISCNT ) {
 			printk("*******************vbus detect*********************\n");
-            if( pldata->bc_detect_cb != NULL )
-                pldata->bc_detect_cb( _pcd->vbus_status = usb_battery_charger_detect(1) );
-            else
+//            if( pldata->bc_detect_cb != NULL )
+//                pldata->bc_detect_cb( _pcd->vbus_status = usb_battery_charger_detect(1) );
+//            else
                 _pcd->vbus_status = USB_BC_TYPE_SDP;
 			if(_pcd->conn_en){
 				goto connect;
@@ -1540,10 +1540,13 @@ static void dwc_otg_pcd_check_vbus_work( struct work_struct *work )
 			 */
 			dwc_otg_msc_unlock(_pcd);
 			_pcd->conn_status++;
-            if( pldata->bc_detect_cb != NULL )
-               pldata->bc_detect_cb( _pcd->vbus_status = USB_BC_TYPE_DCP ); 
-            else
+            if( pldata->bc_detect_cb != NULL ){
+                rk_usb_charger_status = USB_BC_TYPE_DCP;
+                pldata->bc_detect_cb( _pcd->vbus_status = USB_BC_TYPE_DCP ); 
+            }else{
                 _pcd->vbus_status = USB_BC_TYPE_DCP;
+                rk_usb_charger_status = USB_BC_TYPE_DCP;
+			}
 			/* fail to connect, suspend usb phy and disable clk */
 			if( pldata->phy_status == USB_PHY_ENABLED ){
 				pldata->phy_suspend(pldata, USB_PHY_SUSPEND);
diff --git a/drivers/usb/dwc_otg_310/usbdev_bc.c b/drivers/usb/dwc_otg_310/usbdev_bc.c
old mode 100644
new mode 100755
index c2e63f012ebe..d08d894336c3
--- a/drivers/usb/dwc_otg_310/usbdev_bc.c
+++ b/drivers/usb/dwc_otg_310/usbdev_bc.c
@@ -23,6 +23,7 @@
 
 uoc_field_t *pBC_UOC_FIELDS = NULL;
 static void *pGRF_BASE = NULL;
+int rk_usb_charger_status = USB_BC_TYPE_DISCNT;
 
 /****** GET REGISTER FIELD INFO FROM Device Tree ******/
 
@@ -223,7 +224,33 @@ EXPORT_SYMBOL(usb_battery_charger_detect);
 
 int dwc_otg_check_dpdm(bool wait)
 {
-    return usb_battery_charger_detect(wait);
+    static struct device_node *np = NULL;
+    if(!np)
+        np = of_find_node_by_name(NULL, "usb_bc");
+    if(!np)
+        return -1;
+    if(!pGRF_BASE) {
+        pGRF_BASE = get_grf_base(np);
+    }
+
+    if(of_device_is_compatible(np,"rockchip,ctrl")) {
+        if(!pBC_UOC_FIELDS)
+            uoc_init_rk(np);
+		if(!BC_GET(RK_BC_BVALID))
+			rk_usb_charger_status = USB_BC_TYPE_DISCNT;
+
+    }else if(of_device_is_compatible(np,"synopsys,phy")) {
+        if(!pBC_UOC_FIELDS)
+            uoc_init_synop(np);
+		if(!BC_GET(SYNOP_BC_BVALID))
+			rk_usb_charger_status = USB_BC_TYPE_DISCNT;
+
+    }else if(of_device_is_compatible(np,"inno,phy")) {
+        if(!pBC_UOC_FIELDS)
+            uoc_init_inno(np);
+    }
+
+    return rk_usb_charger_status;
 }
 EXPORT_SYMBOL(dwc_otg_check_dpdm);
 
diff --git a/drivers/usb/dwc_otg_310/usbdev_rk.h b/drivers/usb/dwc_otg_310/usbdev_rk.h
index f459e0fdb8fa..288597760084 100755
--- a/drivers/usb/dwc_otg_310/usbdev_rk.h
+++ b/drivers/usb/dwc_otg_310/usbdev_rk.h
@@ -38,6 +38,7 @@
 #define USB_REMOTE_WAKEUP     (6)
 #define USB_IRQ_WAKEUP        (7)
 
+extern int rk_usb_charger_status;
 /* rk3188 platform data */
 extern struct dwc_otg_platform_data usb20otg_pdata_rk3188;
 extern struct dwc_otg_platform_data usb20host_pdata_rk3188;
@@ -96,6 +97,7 @@ struct dwc_otg_control_usb {
 	struct gpio *otg_gpios;
 	struct clk* hclk_usb_peri;
 	struct delayed_work usb_det_wakeup_work;
+	struct delayed_work usb_charger_det_work;
 	struct wake_lock usb_wakelock;
 	int remote_wakeup;
 	int usb_irq_wakeup;
diff --git a/drivers/usb/dwc_otg_310/usbdev_rk32.c b/drivers/usb/dwc_otg_310/usbdev_rk32.c
index faa058a2d292..731e5a49dd60 100755
--- a/drivers/usb/dwc_otg_310/usbdev_rk32.c
+++ b/drivers/usb/dwc_otg_310/usbdev_rk32.c
@@ -534,6 +534,10 @@ inline static void do_wakeup(struct work_struct *work)
 //      rk28_send_wakeup_key();
 }
 
+static void usb_battery_charger_detect_work(struct work_struct *work)
+{
+	rk_usb_charger_status = usb_battery_charger_detect(0);
+}
 /********** handler for bvalid irq **********/
 static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
 {
@@ -549,6 +553,10 @@ static irqreturn_t bvalid_irq_handler(int irq, void *dev_id)
 		wake_lock_timeout(&control_usb->usb_wakelock, WAKE_LOCK_TIMEOUT);
 		schedule_delayed_work(&control_usb->usb_det_wakeup_work, HZ/10);
 	}
+
+	rk_usb_charger_status = USB_BC_TYPE_SDP;
+	schedule_delayed_work(&control_usb->usb_charger_det_work, HZ/10);
+
 	return IRQ_HANDLED;
 }
 
@@ -634,7 +642,7 @@ static int otg_irq_detect_init(struct platform_device *pdev)
 			}
 		}
 	}
-
+#if 0
     /*register otg_id irq*/
     irq = platform_get_irq_byname(pdev, "otg_id");
     if(irq > 0){
@@ -694,7 +702,7 @@ static int otg_irq_detect_init(struct platform_device *pdev)
 			}
 		}
     }
-	
+#endif	
 	return ret;
 }
 
@@ -829,6 +837,7 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
 	control_usb->usb_irq_wakeup = of_property_read_bool(np,
 		"rockchip,usb_irq_wakeup");
 
+	INIT_DELAYED_WORK(&control_usb->usb_charger_det_work, usb_battery_charger_detect_work);
 /*	disable for debug
 	hclk_usb_peri = devm_clk_get(&pdev->dev, "hclk_usb_peri");
 	if (IS_ERR(hclk_usb_peri)) {
@@ -894,11 +903,15 @@ static int dwc_otg_control_usb_probe(struct platform_device *pdev)
 	}
 	gpio_direction_output(control_usb->otg_gpios->gpio, 0);
 
-/* disable for debug
+	if(usb20otg_get_status(USB_STATUS_BVABLID)){
+		rk_usb_charger_status = USB_BC_TYPE_SDP;
+		schedule_delayed_work(&control_usb->usb_charger_det_work, HZ/10);
+	}
+
 	ret = otg_irq_detect_init(pdev);
 	if (ret < 0)
 		goto err2;
-*/
+
 	return 0;
 
 err2:
-- 
2.34.1