USB: dwc3: Add support for host bus suspend

Add required support for host bus suspend for dwc3 driver. Also add
pm runtime callbacks for xhci platform device which will defer  putting
USB hardware in/out of low power mode to transciever driver. Whenever USB
core autosuspend timer expires, USB2 and USB3 roothubs are suspended, then
xhci platform device is runtime suspended. when xhci's runtime suspend
happens, it will call USB transciever's set_suspend callback which puts
USB hardware in low power mode.

When remote wakeup happens, dwc3 driver will bring USB hardware out of low
power mode. Then xhci stack will resume roothub port on which port change
is detected. Set skip resume flag to resume USB only on remote wakeup.

When micro A cable is disconnected during system suspend, xhci platform
device will be removed before PM resume of xhci device. Due to this,disable
depth counter mismatch happens and xhci device will not not be pm runtime
enabled on next cable connect. Fix this issue by calling pm_runtime_init
for xhci platform device.

CRs-Fixed: 422306
Change-Id: Ia06f792979d7bd3248ae40161978f9632ccd7808
Signed-off-by: Vijayavardhan Vennapusa <vvreddy@codeaurora.org>
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index eb879e3..4980337 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -1,7 +1,7 @@
 /**
  * dwc3_otg.c - DesignWare USB3 DRD Controller OTG
  *
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, 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
@@ -55,6 +55,25 @@
 	}
 }
 
+static int dwc3_otg_set_suspend(struct usb_phy *phy, int suspend)
+{
+	struct usb_otg *otg = phy->otg;
+	struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
+
+	if (dotg->host_bus_suspend == suspend)
+		return 0;
+
+	dotg->host_bus_suspend = suspend;
+	if (suspend) {
+		pm_runtime_put_sync(phy->dev);
+	} else {
+		pm_runtime_get_noresume(phy->dev);
+		pm_runtime_resume(phy->dev);
+	}
+
+	return 0;
+}
+
 /**
  * dwc3_otg_set_host_power - Enable port power control for host operation
  *
@@ -149,6 +168,14 @@
 		 * anymore.
 		 */
 		dwc3_otg_set_host_regs(dotg);
+		/*
+		 * FIXME If micro A cable is disconnected during system suspend,
+		 * xhci platform device will be removed before runtime pm is
+		 * enabled for xhci device. Due to this, disable_depth becomes
+		 * greater than one and runtimepm is not enabled for next microA
+		 * connect. Fix this by calling pm_runtime_init for xhci device.
+		 */
+		pm_runtime_init(&dwc->xhci->dev);
 		ret = platform_device_add(dwc->xhci);
 		if (ret) {
 			dev_err(otg->phy->dev,
@@ -353,6 +380,9 @@
 			dev_dbg(phy->dev, "ext PHY_RESUME event received\n");
 			/* ext_xceiver would have taken h/w out of LPM by now */
 			ret = pm_runtime_get(phy->dev);
+			if ((phy->state == OTG_STATE_A_HOST) &&
+							dotg->host_bus_suspend)
+				dotg->host_bus_suspend = 0;
 			if (ret == -EACCES) {
 				/* pm_runtime_get may fail during system
 				   resume with -EACCES error */
@@ -852,6 +882,7 @@
 	dotg->otg.phy->otg = &dotg->otg;
 	dotg->otg.phy->dev = dwc->dev;
 	dotg->otg.phy->set_power = dwc3_otg_set_power;
+	dotg->otg.phy->set_suspend = dwc3_otg_set_suspend;
 
 	ret = usb_set_transceiver(dotg->otg.phy);
 	if (ret) {