Merge "USB: ehci-msm-hsic: Apply PHY lockup workarounds only for affected cores"
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 1fb2ba9..6ea9e62 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -38,6 +38,9 @@
   STROBE GPIO PAD.
 - hsic,data-pad-offset : Offset of TLMM register for configuring HSIC
   DATA GPIO PAD.
+- qcom,phy-sof-workaround : If present then HSIC PHY has h/w BUGs related to
+  SOFs. Software workarounds are required for the same.
+
 - Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
   below optional properties:
     - qcom,msm_bus,name
diff --git a/arch/arm/boot/dts/msm8974-v1-cdp.dts b/arch/arm/boot/dts/msm8974-v1-cdp.dts
index 33bd1fb..bbefe88 100644
--- a/arch/arm/boot/dts/msm8974-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-cdp.dts
@@ -25,3 +25,7 @@
 	status = "ok";
 	vbus-supply = <&usb2_otg_sw>;
 };
+
+&hsic_host {
+       qcom,phy-sof-workaround;
+};
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index 54aa02a..ad95601 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -57,3 +57,7 @@
 &ldrex_spinlock {
 	status = "ok";
 };
+
+&hsic_host {
+	qcom,phy-sof-workaround;
+};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 3dbc95d..5a8a5ae 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -108,7 +108,7 @@
 				<87 512 40000 640000>;
 	};
 
-	hsic@f9a15000 {
+	hsic_host: hsic@f9a15000 {
 		compatible = "qcom,hsic-host";
 		reg = <0xf9a15000 0x400>;
 		interrupts = <0 136 0>, <0 148 0>;
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 42bde8f..623289e 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -675,6 +675,7 @@
 static struct msm_hsic_host_platform_data msm_hsic_pdata = {
 	.strobe			= 88,
 	.data			= 89,
+	.phy_sof_workaround	= true,
 	.bus_scale_table	= &hsic_bus_scale_pdata,
 };
 #else
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 7ef6fed..f3d8a2f 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1459,8 +1459,9 @@
 #ifdef CONFIG_USB_EHCI_MSM_HSIC
 #define HSIC_HUB_RESET_GPIO	91
 static struct msm_hsic_host_platform_data msm_hsic_pdata = {
-	.strobe		= 150,
-	.data		= 151,
+	.strobe			= 150,
+	.data			= 151,
+	.phy_sof_workaround	= true,
 };
 
 static struct smsc_hub_platform_data hsic_hub_pdata = {
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 50f4fd7..b77a3b9 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -841,6 +841,10 @@
 	.prv_data = &msm_hsic_peripheral_pdata_private,
 };
 
+static struct msm_hsic_host_platform_data msm_hsic_pdata = {
+	.phy_sof_workaround	= true,
+};
+
 #define PID_MAGIC_ID		0x71432909
 #define SERIAL_NUM_MAGIC_ID	0x61945374
 #define SERIAL_NUMBER_LENGTH	127
@@ -1073,6 +1077,7 @@
 		&msm_peripheral_pdata;
 	msm_device_hsic_peripheral.dev.platform_data =
 		&msm_hsic_peripheral_pdata;
+	msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
 	msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm9615_pm8xxx_gpio_mpp_init();
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 9879122..4a085aa 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1332,44 +1332,48 @@
 	if (pdata->resume_gpio)
 		gpio_direction_output(pdata->resume_gpio, 1);
 
-	mehci->resume_status = 0;
-	resume_thread = kthread_run(msm_hsic_resume_thread,
-			mehci, "hsic_resume_thread");
-	if (IS_ERR(resume_thread)) {
-		pr_err("Error creating resume thread:%lu\n",
-				PTR_ERR(resume_thread));
-		return PTR_ERR(resume_thread);
+	if (!mehci->ehci.resume_sof_bug) {
+		ehci_bus_resume(hcd);
+	} else {
+		mehci->resume_status = 0;
+		resume_thread = kthread_run(msm_hsic_resume_thread,
+				mehci, "hsic_resume_thread");
+		if (IS_ERR(resume_thread)) {
+			pr_err("Error creating resume thread:%lu\n",
+					PTR_ERR(resume_thread));
+			return PTR_ERR(resume_thread);
+		}
+
+		wait_for_completion(&mehci->rt_completion);
+
+		if (mehci->resume_status < 0)
+			return mehci->resume_status;
+
+		dbg_log_event(NULL, "FPR: Wokeup", 0);
+		spin_lock_irq(&ehci->lock);
+		(void) ehci_readl(ehci, &ehci->regs->command);
+
+		temp = 0;
+		if (ehci->async->qh_next.qh)
+			temp |= CMD_ASE;
+		if (ehci->periodic_sched)
+			temp |= CMD_PSE;
+		if (temp) {
+			ehci->command |= temp;
+			ehci_writel(ehci, ehci->command, &ehci->regs->command);
+		}
+
+		ehci->next_statechange = jiffies + msecs_to_jiffies(5);
+		hcd->state = HC_STATE_RUNNING;
+		ehci->rh_state = EHCI_RH_RUNNING;
+		ehci->command |= CMD_RUN;
+
+		/* Now we can safely re-enable irqs */
+		ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+
+		spin_unlock_irq(&ehci->lock);
 	}
 
-	wait_for_completion(&mehci->rt_completion);
-
-	if (mehci->resume_status < 0)
-		return mehci->resume_status;
-
-	dbg_log_event(NULL, "FPR: Wokeup", 0);
-	spin_lock_irq(&ehci->lock);
-	(void) ehci_readl(ehci, &ehci->regs->command);
-
-	temp = 0;
-	if (ehci->async->qh_next.qh)
-		temp |= CMD_ASE;
-	if (ehci->periodic_sched)
-		temp |= CMD_PSE;
-	if (temp) {
-		ehci->command |= temp;
-		ehci_writel(ehci, ehci->command, &ehci->regs->command);
-	}
-
-	ehci->next_statechange = jiffies + msecs_to_jiffies(5);
-	hcd->state = HC_STATE_RUNNING;
-	ehci->rh_state = EHCI_RH_RUNNING;
-	ehci->command |= CMD_RUN;
-
-	/* Now we can safely re-enable irqs */
-	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
-
-	spin_unlock_irq(&ehci->lock);
-
 	if (pdata->resume_gpio)
 		gpio_direction_output(pdata->resume_gpio, 0);
 
@@ -1808,6 +1812,8 @@
 		res_gpio = 0;
 	pdata->resume_gpio = res_gpio;
 
+	pdata->phy_sof_workaround = of_property_read_bool(node,
+					"qcom,phy-sof-workaround");
 	pdata->ignore_cal_pad_config = of_property_read_bool(node,
 					"hsic,ignore-cal-pad-config");
 	of_property_read_u32(node, "hsic,strobe-pad-offset",
@@ -1899,10 +1905,12 @@
 
 	spin_lock_init(&mehci->wakeup_lock);
 
-	mehci->ehci.susp_sof_bug = 1;
-	mehci->ehci.reset_sof_bug = 1;
+	if (pdata->phy_sof_workaround) {
+		mehci->ehci.susp_sof_bug = 1;
+		mehci->ehci.reset_sof_bug = 1;
+		mehci->ehci.resume_sof_bug = 1;
+	}
 
-	mehci->ehci.resume_sof_bug = 1;
 	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
 	mehci->enable_hbm = pdata->enable_hbm;
 
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index bf6847a..c8a20da 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -402,6 +402,7 @@
 	unsigned strobe;
 	unsigned data;
 	bool ignore_cal_pad_config;
+	bool phy_sof_workaround;
 	int strobe_pad_offset;
 	int data_pad_offset;