usb: gadget: mv_udc: refine suspend/resume function
authorNeil Zhang <zhangwm@marvell.com>
Wed, 30 Nov 2011 01:57:16 +0000 (09:57 +0800)
committerFelipe Balbi <balbi@ti.com>
Mon, 12 Dec 2011 09:45:24 +0000 (11:45 +0200)
This patch impletments system suspend/resume functions for Marvell
otg controller.
If OTG is enabled, OTG driver will do most of the work.
If not, we will check clock gating.
  If clock gating is enabled, the UDC will be start/stop automatically.
  If not, UDC will be start/stop in suspend/resume functions.

Signed-off-by: Neil Zhang <zhangwm@marvell.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
drivers/usb/gadget/mv_udc_core.c

index 77e906556378cbc3e8eae20b57c4547cdec47207..143925c6a1840a1bc1fd941f80ef2a9a4b7b71a6 100644 (file)
@@ -2447,7 +2447,30 @@ static int mv_udc_suspend(struct device *_dev)
 {
        struct mv_udc *udc = the_controller;
 
-       udc_stop(udc);
+       /* if OTG is enabled, the following will be done in OTG driver*/
+       if (udc->transceiver)
+               return 0;
+
+       if (udc->pdata->vbus && udc->pdata->vbus->poll)
+               if (udc->pdata->vbus->poll() == VBUS_HIGH) {
+                       dev_info(&udc->dev->dev, "USB cable is connected!\n");
+                       return -EAGAIN;
+               }
+
+       /*
+        * only cable is unplugged, udc can suspend.
+        * So do not care about clock_gating == 1.
+        */
+       if (!udc->clock_gating) {
+               udc_stop(udc);
+
+               spin_lock_irq(&udc->lock);
+               /* stop all usb activities */
+               stop_activity(udc, udc->driver);
+               spin_unlock_irq(&udc->lock);
+
+               mv_udc_disable_internal(udc);
+       }
 
        return 0;
 }
@@ -2457,20 +2480,22 @@ static int mv_udc_resume(struct device *_dev)
        struct mv_udc *udc = the_controller;
        int retval;
 
-       if (udc->pdata->phy_init) {
-               retval = udc->pdata->phy_init(udc->phy_regs);
-               if (retval) {
-                       dev_err(&udc->dev->dev,
-                               "init phy error %d when resume back\n",
-                               retval);
+       /* if OTG is enabled, the following will be done in OTG driver*/
+       if (udc->transceiver)
+               return 0;
+
+       if (!udc->clock_gating) {
+               retval = mv_udc_enable_internal(udc);
+               if (retval)
                        return retval;
+
+               if (udc->driver && udc->softconnect) {
+                       udc_reset(udc);
+                       ep0_reset(udc);
+                       udc_start(udc);
                }
        }
 
-       udc_reset(udc);
-       ep0_reset(udc);
-       udc_start(udc);
-
        return 0;
 }