i2c-gpio: Move initialization code to subsys_initcall()
[firefly-linux-kernel-4.4.55.git] / drivers / i2c / i2c-core.c
index c2258a51fe0ce3bb09055220c645602ab467c876..7c469a62c3c145b547d7c8948252b7ca9a51bde2 100644 (file)
@@ -159,107 +159,131 @@ static void i2c_device_shutdown(struct device *dev)
                driver->shutdown(client);
 }
 
-#ifdef CONFIG_SUSPEND
-static int i2c_device_pm_suspend(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int i2c_legacy_suspend(struct device *dev, pm_message_t mesg)
 {
-       const struct dev_pm_ops *pm;
+       struct i2c_client *client = i2c_verify_client(dev);
+       struct i2c_driver *driver;
 
-       if (!dev->driver)
+       if (!client || !dev->driver)
                return 0;
-       pm = dev->driver->pm;
-       if (!pm || !pm->suspend)
+       driver = to_i2c_driver(dev->driver);
+       if (!driver->suspend)
                return 0;
-       return pm->suspend(dev);
+       return driver->suspend(client, mesg);
 }
 
-static int i2c_device_pm_resume(struct device *dev)
+static int i2c_legacy_resume(struct device *dev)
 {
-       const struct dev_pm_ops *pm;
+       struct i2c_client *client = i2c_verify_client(dev);
+       struct i2c_driver *driver;
 
-       if (!dev->driver)
+       if (!client || !dev->driver)
                return 0;
-       pm = dev->driver->pm;
-       if (!pm || !pm->resume)
+       driver = to_i2c_driver(dev->driver);
+       if (!driver->resume)
                return 0;
-       return pm->resume(dev);
+       return driver->resume(client);
 }
-#else
-#define i2c_device_pm_suspend  NULL
-#define i2c_device_pm_resume   NULL
-#endif
 
-#ifdef CONFIG_PM_RUNTIME
-static int i2c_device_runtime_suspend(struct device *dev)
+static int i2c_device_pm_suspend(struct device *dev)
 {
-       const struct dev_pm_ops *pm;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-       if (!dev->driver)
-               return 0;
-       pm = dev->driver->pm;
-       if (!pm || !pm->runtime_suspend)
+       if (pm_runtime_suspended(dev))
                return 0;
-       return pm->runtime_suspend(dev);
-}
 
-static int i2c_device_runtime_resume(struct device *dev)
-{
-       const struct dev_pm_ops *pm;
+       if (pm)
+               return pm->suspend ? pm->suspend(dev) : 0;
 
-       if (!dev->driver)
-               return 0;
-       pm = dev->driver->pm;
-       if (!pm || !pm->runtime_resume)
-               return 0;
-       return pm->runtime_resume(dev);
+       return i2c_legacy_suspend(dev, PMSG_SUSPEND);
 }
 
-static int i2c_device_runtime_idle(struct device *dev)
+static int i2c_device_pm_resume(struct device *dev)
 {
-       const struct dev_pm_ops *pm = NULL;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
        int ret;
 
-       if (dev->driver)
-               pm = dev->driver->pm;
-       if (pm && pm->runtime_idle) {
-               ret = pm->runtime_idle(dev);
-               if (ret)
-                       return ret;
+       if (pm)
+               ret = pm->resume ? pm->resume(dev) : 0;
+       else
+               ret = i2c_legacy_resume(dev);
+
+       if (!ret) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
        }
 
-       return pm_runtime_suspend(dev);
+       return ret;
 }
-#else
-#define i2c_device_runtime_suspend     NULL
-#define i2c_device_runtime_resume      NULL
-#define i2c_device_runtime_idle                NULL
-#endif
 
-static int i2c_device_suspend(struct device *dev, pm_message_t mesg)
+static int i2c_device_pm_freeze(struct device *dev)
 {
-       struct i2c_client *client = i2c_verify_client(dev);
-       struct i2c_driver *driver;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-       if (!client || !dev->driver)
+       if (pm_runtime_suspended(dev))
                return 0;
-       driver = to_i2c_driver(dev->driver);
-       if (!driver->suspend)
-               return 0;
-       return driver->suspend(client, mesg);
+
+       if (pm)
+               return pm->freeze ? pm->freeze(dev) : 0;
+
+       return i2c_legacy_suspend(dev, PMSG_FREEZE);
 }
 
-static int i2c_device_resume(struct device *dev)
+static int i2c_device_pm_thaw(struct device *dev)
 {
-       struct i2c_client *client = i2c_verify_client(dev);
-       struct i2c_driver *driver;
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
 
-       if (!client || !dev->driver)
+       if (pm_runtime_suspended(dev))
                return 0;
-       driver = to_i2c_driver(dev->driver);
-       if (!driver->resume)
+
+       if (pm)
+               return pm->thaw ? pm->thaw(dev) : 0;
+
+       return i2c_legacy_resume(dev);
+}
+
+static int i2c_device_pm_poweroff(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+
+       if (pm_runtime_suspended(dev))
                return 0;
-       return driver->resume(client);
+
+       if (pm)
+               return pm->poweroff ? pm->poweroff(dev) : 0;
+
+       return i2c_legacy_suspend(dev, PMSG_HIBERNATE);
 }
 
+static int i2c_device_pm_restore(struct device *dev)
+{
+       const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+       int ret;
+
+       if (pm)
+               ret = pm->restore ? pm->restore(dev) : 0;
+       else
+               ret = i2c_legacy_resume(dev);
+
+       if (!ret) {
+               pm_runtime_disable(dev);
+               pm_runtime_set_active(dev);
+               pm_runtime_enable(dev);
+       }
+
+       return ret;
+}
+#else /* !CONFIG_PM_SLEEP */
+#define i2c_device_pm_suspend  NULL
+#define i2c_device_pm_resume   NULL
+#define i2c_device_pm_freeze   NULL
+#define i2c_device_pm_thaw     NULL
+#define i2c_device_pm_poweroff NULL
+#define i2c_device_pm_restore  NULL
+#endif /* !CONFIG_PM_SLEEP */
+
 static void i2c_client_dev_release(struct device *dev)
 {
        kfree(to_i2c_client(dev));
@@ -301,9 +325,15 @@ static const struct attribute_group *i2c_dev_attr_groups[] = {
 static const struct dev_pm_ops i2c_device_pm_ops = {
        .suspend = i2c_device_pm_suspend,
        .resume = i2c_device_pm_resume,
-       .runtime_suspend = i2c_device_runtime_suspend,
-       .runtime_resume = i2c_device_runtime_resume,
-       .runtime_idle = i2c_device_runtime_idle,
+       .freeze = i2c_device_pm_freeze,
+       .thaw = i2c_device_pm_thaw,
+       .poweroff = i2c_device_pm_poweroff,
+       .restore = i2c_device_pm_restore,
+       SET_RUNTIME_PM_OPS(
+               pm_generic_runtime_suspend,
+               pm_generic_runtime_resume,
+               pm_generic_runtime_idle
+       )
 };
 
 struct bus_type i2c_bus_type = {
@@ -312,8 +342,6 @@ struct bus_type i2c_bus_type = {
        .probe          = i2c_device_probe,
        .remove         = i2c_device_remove,
        .shutdown       = i2c_device_shutdown,
-       .suspend        = i2c_device_suspend,
-       .resume         = i2c_device_resume,
        .pm             = &i2c_device_pm_ops,
 };
 EXPORT_SYMBOL_GPL(i2c_bus_type);