usb: gadget: renesas_usbhs: add suspend/resume support
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Tue, 11 Oct 2011 04:58:19 +0000 (21:58 -0700)
committerFelipe Balbi <balbi@ti.com>
Thu, 13 Oct 2011 17:40:00 +0000 (20:40 +0300)
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/renesas_usbhs/common.c

index d8239e5efa6691275ea4a1a2176fae251233538e..319ed47153d7e39b38190872e70beff4df7f3a0c 100644 (file)
@@ -203,13 +203,10 @@ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable)
 }
 
 /*
- *             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 @@ static void usbhsc_notify_hotplug(struct work_struct *work)
        }
 }
 
+/*
+ *             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 @@ static int __devexit usbhs_remove(struct platform_device *pdev)
        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),