Merge "ARM: msm: dts: Enable sdp check timer for msm8909w"
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 431c32a..f1130e8 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -191,6 +191,8 @@
 	both "USB" and "USB-HOST" events.
 - qcom,phy-id-high-as-peripheral: If present, specifies device to switch to device mode
 	if PHY ID state is high or host mode if PHY ID state is low.
+- qcom,enumeration-check-for-sdp: If present, start timer for SDP charger to check enumeration
+	happen or not.
 
 Example HSUSB OTG controller device node :
 	usb@f9690000 {
diff --git a/arch/arm64/boot/dts/qcom/msm8909w.dtsi b/arch/arm64/boot/dts/qcom/msm8909w.dtsi
index 7229564..c023650 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909w.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -75,6 +75,10 @@
 	};
 };
 
+&usb_otg {
+	qcom,enumeration-check-for-sdp;
+};
+
 &qcom_crypto {
 	qcom,msm-bus,vectors-KBps =
 		<55 512 0 0>,
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 2e300a3..be3172e 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -400,7 +400,9 @@
 		hw_cwrite(CAP_USBINTR, ~0,
 			     USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
 		hw_cwrite(CAP_USBCMD, USBCMD_RS, USBCMD_RS);
+		udc->transceiver->flags |= PHY_SOFT_CONNECT;
 	} else {
+		udc->transceiver->flags &= ~PHY_SOFT_CONNECT;
 		hw_cwrite(CAP_USBCMD, USBCMD_RS, 0);
 		hw_cwrite(CAP_USBINTR, ~0, 0);
 		/* Clear BIT(31) to disable AHB2AHB Bypass functionality */
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index a74a0aa..c9366c5 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -218,6 +218,7 @@
 };
 
 #define SDP_CHECK_DELAY_MS 10000 /* in ms */
+#define SDP_CHECK_BOOT_DELAY_MS 30000 /* in ms */
 
 #define MSM_USB_BASE	(motg->regs)
 #define MSM_USB_PHY_CSR_BASE (motg->phy_csr_regs)
@@ -1919,12 +1920,13 @@
 							motg->chg_type);
 
 	psy_type = get_psy_type(motg);
-	if (psy_type == POWER_SUPPLY_TYPE_USB_FLOAT) {
-		if (!mA)
+	if (psy_type == POWER_SUPPLY_TYPE_USB_FLOAT ||
+		(psy_type == POWER_SUPPLY_TYPE_USB &&
+			motg->enable_sdp_check_timer)) {
+		if (!mA) {
 			pval.intval = -ETIMEDOUT;
-		else
-			pval.intval = 1000 * mA;
-		goto set_prop;
+			goto set_prop;
+		}
 	}
 
 	if (motg->cur_power == mA)
@@ -2775,7 +2777,7 @@
 	struct msm_otg *motg = container_of(w, struct msm_otg, sdp_check.work);
 
 	/* Cable disconnected or device enumerated as SDP */
-	if (!motg->vbus_state || motg->phy.otg->gadget->state >=
+	if (!motg->vbus_state || motg->phy.otg->gadget->state >
 							USB_STATE_DEFAULT)
 		return;
 
@@ -2856,13 +2858,18 @@
 				break;
 			}
 
-			if (get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_FLOAT)
-				queue_delayed_work(motg->otg_wq,
-				  &motg->sdp_check,
-				  msecs_to_jiffies(SDP_CHECK_DELAY_MS));
-
 			pm_runtime_get_sync(otg->usb_phy->dev);
 			msm_otg_start_peripheral(otg, 1);
+			if (get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_FLOAT ||
+				(get_psy_type(motg) == POWER_SUPPLY_TYPE_USB &&
+				motg->enable_sdp_check_timer)) {
+				queue_delayed_work(motg->otg_wq,
+					&motg->sdp_check,
+					msecs_to_jiffies(
+					(phy->flags & PHY_SOFT_CONNECT) ?
+					SDP_CHECK_DELAY_MS :
+					SDP_CHECK_BOOT_DELAY_MS));
+			}
 			otg->state = OTG_STATE_B_PERIPHERAL;
 		} else {
 			pr_debug("Cable disconnected\n");
@@ -4116,6 +4123,9 @@
 	of_property_read_u32(pdev->dev.of_node, "qcom,pm-qos-latency",
 				&motg->pm_qos_latency);
 
+	motg->enable_sdp_check_timer = of_property_read_bool(pdev->dev.of_node,
+				"qcom,enumeration-check-for-sdp");
+
 	pdata = msm_otg_dt_to_pdata(pdev);
 	if (!pdata) {
 		ret = -ENOMEM;
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 0e7f7c5..f010249 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2008 Google, Inc.
  * Author: Brian Swetland <swetland@google.com>
- * Copyright (c) 2009-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2019, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -319,6 +319,7 @@
 	struct work_struct notify_charger_work;
 	struct work_struct extcon_register_work;
 	struct notifier_block psy_nb;
+	bool enable_sdp_check_timer;
 };
 
 struct ci13xxx_platform_data {
diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h
index 4caac13..c724747 100644
--- a/include/linux/usb/phy.h
+++ b/include/linux/usb/phy.h
@@ -23,6 +23,7 @@
 #define PHY_HSFS_MODE		BIT(8)
 #define PHY_LS_MODE		BIT(9)
 #define PHY_USB_DP_CONCURRENT_MODE	BIT(10)
+#define PHY_SOFT_CONNECT	BIT(11)
 
 enum usb_phy_interface {
 	USBPHY_INTERFACE_MODE_UNKNOWN,