usb: gadget: renesas_usbhs: add suspend/resume support

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index d8239e5..319ed47 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -203,13 +203,10 @@
 }
 
 /*
- *		notify hotplug
+ *		hotplug
  */
-static void usbhsc_notify_hotplug(struct work_struct *work)
+static void usbhsc_hotplug(struct usbhs_priv *priv)
 {
-	struct usbhs_priv *priv = container_of(work,
-					       struct usbhs_priv,
-					       notify_hotplug_work.work);
 	struct platform_device *pdev = usbhs_priv_to_pdev(priv);
 	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
 	int id;
@@ -257,6 +254,17 @@
 	}
 }
 
+/*
+ *		notify hotplug
+ */
+static void usbhsc_notify_hotplug(struct work_struct *work)
+{
+	struct usbhs_priv *priv = container_of(work,
+					       struct usbhs_priv,
+					       notify_hotplug_work.work);
+	usbhsc_hotplug(priv);
+}
+
 int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
 {
 	struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
@@ -443,9 +451,60 @@
 	return 0;
 }
 
+static int usbhsc_suspend(struct device *dev)
+{
+	struct usbhs_priv *priv = dev_get_drvdata(dev);
+	struct usbhs_mod *mod = usbhs_mod_get_current(priv);
+
+	if (mod) {
+		usbhs_mod_call(priv, stop, priv);
+		usbhs_mod_change(priv, -1);
+	}
+
+	if (mod || !usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+		usbhsc_power_ctrl(priv, 0);
+
+	return 0;
+}
+
+static int usbhsc_resume(struct device *dev)
+{
+	struct usbhs_priv *priv = dev_get_drvdata(dev);
+	struct platform_device *pdev = usbhs_priv_to_pdev(priv);
+
+	usbhs_platform_call(priv, phy_reset, pdev);
+
+	if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+		usbhsc_power_ctrl(priv, 1);
+
+	usbhsc_hotplug(priv);
+
+	return 0;
+}
+
+static int usbhsc_runtime_nop(struct device *dev)
+{
+	/* Runtime PM callback shared between ->runtime_suspend()
+	 * and ->runtime_resume(). Simply returns success.
+	 *
+	 * This driver re-initializes all registers after
+	 * pm_runtime_get_sync() anyway so there is no need
+	 * to save and restore registers here.
+	 */
+	return 0;
+}
+
+static const struct dev_pm_ops usbhsc_pm_ops = {
+	.suspend		= usbhsc_suspend,
+	.resume			= usbhsc_resume,
+	.runtime_suspend	= usbhsc_runtime_nop,
+	.runtime_resume		= usbhsc_runtime_nop,
+};
+
 static struct platform_driver renesas_usbhs_driver = {
 	.driver		= {
 		.name	= "renesas_usbhs",
+		.pm	= &usbhsc_pm_ops,
 	},
 	.probe		= usbhs_probe,
 	.remove		= __devexit_p(usbhs_remove),