]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/spi/spi.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / spi / spi.c
index b02d0cbce89049e003fe8300421adeed847e92ce..34bb17f030197d0ab395e17b75475ff30c123ec5 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/spi/spi.h>
 #include <linux/of_spi.h>
+#include <linux/pm_runtime.h>
 
 static void spidev_release(struct device *dev)
 {
@@ -100,9 +101,8 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
        return 0;
 }
 
-#ifdef CONFIG_PM
-
-static int spi_suspend(struct device *dev, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int spi_legacy_suspend(struct device *dev, pm_message_t message)
 {
        int                     value = 0;
        struct spi_driver       *drv = to_spi_driver(dev->driver);
@@ -117,7 +117,7 @@ static int spi_suspend(struct device *dev, pm_message_t message)
        return value;
 }
 
-static int spi_resume(struct device *dev)
+static int spi_legacy_resume(struct device *dev)
 {
        int                     value = 0;
        struct spi_driver       *drv = to_spi_driver(dev->driver);
@@ -132,18 +132,94 @@ static int spi_resume(struct device *dev)
        return value;
 }
 
+static int spi_pm_suspend(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm)
+               return pm_generic_suspend(dev);
+       else
+               return spi_legacy_suspend(dev, PMSG_SUSPEND);
+}
+
+static int spi_pm_resume(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm)
+               return pm_generic_resume(dev);
+       else
+               return spi_legacy_resume(dev);
+}
+
+static int spi_pm_freeze(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm)
+               return pm_generic_freeze(dev);
+       else
+               return spi_legacy_suspend(dev, PMSG_FREEZE);
+}
+
+static int spi_pm_thaw(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm)
+               return pm_generic_thaw(dev);
+       else
+               return spi_legacy_resume(dev);
+}
+
+static int spi_pm_poweroff(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm)
+               return pm_generic_poweroff(dev);
+       else
+               return spi_legacy_suspend(dev, PMSG_HIBERNATE);
+}
+
+static int spi_pm_restore(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm)
+               return pm_generic_restore(dev);
+       else
+               return spi_legacy_resume(dev);
+}
 #else
-#define spi_suspend    NULL
-#define spi_resume     NULL
+#define spi_pm_suspend NULL
+#define spi_pm_resume  NULL
+#define spi_pm_freeze  NULL
+#define spi_pm_thaw    NULL
+#define spi_pm_poweroff        NULL
+#define spi_pm_restore NULL
 #endif
 
+static const struct dev_pm_ops spi_pm = {
+       .suspend = spi_pm_suspend,
+       .resume = spi_pm_resume,
+       .freeze = spi_pm_freeze,
+       .thaw = spi_pm_thaw,
+       .poweroff = spi_pm_poweroff,
+       .restore = spi_pm_restore,
+       SET_RUNTIME_PM_OPS(
+               pm_generic_runtime_suspend,
+               pm_generic_runtime_resume,
+               pm_generic_runtime_idle
+       )
+};
+
 struct bus_type spi_bus_type = {
        .name           = "spi",
        .dev_attrs      = spi_dev_attrs,
        .match          = spi_match_device,
        .uevent         = spi_uevent,
-       .suspend        = spi_suspend,
-       .resume         = spi_resume,
+       .pm             = &spi_pm,
 };
 EXPORT_SYMBOL_GPL(spi_bus_type);