USB: ohci-s3c2410: add PM support
authorJingoo Han <jg1.han@samsung.com>
Mon, 28 Nov 2011 06:56:06 +0000 (15:56 +0900)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 30 Nov 2011 11:08:26 +0000 (20:08 +0900)
This patch adds power management support such as suspend and resume
functions.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/ohci-s3c2410.c

index a1877c47601e8df0df50ad6f9280906a8d4bb9c5..56dcf069246d53808c6306f0126cf639c1ada348 100644 (file)
@@ -486,15 +486,66 @@ static int __devexit ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int ohci_hcd_s3c2410_drv_suspend(struct device *dev)
+{
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       struct platform_device *pdev = to_platform_device(dev);
+       unsigned long flags;
+       int rc = 0;
+
+       /*
+        * Root hub was already suspended. Disable irq emission and
+        * mark HW unaccessible, bail out if RH has been resumed. Use
+        * the spinlock to properly synchronize with possible pending
+        * RH suspend or resume activity.
+        */
+       spin_lock_irqsave(&ohci->lock, flags);
+       if (ohci->rh_state != OHCI_RH_SUSPENDED) {
+               rc = -EINVAL;
+               goto bail;
+       }
+
+       clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+       s3c2410_stop_hc(pdev);
+bail:
+       spin_unlock_irqrestore(&ohci->lock, flags);
+
+       return rc;
+}
+
+static int ohci_hcd_s3c2410_drv_resume(struct device *dev)
+{
+       struct usb_hcd *hcd = dev_get_drvdata(dev);
+       struct platform_device *pdev = to_platform_device(dev);
+
+       s3c2410_start_hc(pdev, hcd);
+
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       ohci_finish_controller_resume(hcd);
+
+       return 0;
+}
+#else
+#define ohci_hcd_s3c2410_drv_suspend   NULL
+#define ohci_hcd_s3c2410_drv_resume    NULL
+#endif
+
+static const struct dev_pm_ops ohci_hcd_s3c2410_pm_ops = {
+       .suspend        = ohci_hcd_s3c2410_drv_suspend,
+       .resume         = ohci_hcd_s3c2410_drv_resume,
+};
+
 static struct platform_driver ohci_hcd_s3c2410_driver = {
        .probe          = ohci_hcd_s3c2410_drv_probe,
        .remove         = __devexit_p(ohci_hcd_s3c2410_drv_remove),
        .shutdown       = usb_hcd_platform_shutdown,
-       /*.suspend      = ohci_hcd_s3c2410_drv_suspend, */
-       /*.resume       = ohci_hcd_s3c2410_drv_resume, */
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "s3c2410-ohci",
+               .pm     = &ohci_hcd_s3c2410_pm_ops,
        },
 };