i2c: Add driver suspend/resume/shutdown support
Driver model updates for the I2C core:
- Add new suspend(), resume(), and shutdown() methods. Use them in the
standard driver model style; document them.
- Minor doc updates to highlight zero-initialized fields in drivers, and
the driver model accessors for "clientdata".
If any i2c drivers were previously using the old suspend/resume calls
in "struct driver", they were getting warning messages ... and will
now no longer work. Other than that, this patch changes no behaviors;
and it lets I2C drivers use conventional PM and shutdown support.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 60f6eb1..9653f7f 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -41,30 +41,15 @@
static DEFINE_MUTEX(core_lists);
static DEFINE_IDR(i2c_adapter_idr);
+
+/* ------------------------------------------------------------------------- */
+
/* match always succeeds, as we want the probe() to tell if we really accept this match */
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
return 1;
}
-static int i2c_bus_suspend(struct device * dev, pm_message_t state)
-{
- int rc = 0;
-
- if (dev->driver && dev->driver->suspend)
- rc = dev->driver->suspend(dev, state);
- return rc;
-}
-
-static int i2c_bus_resume(struct device * dev)
-{
- int rc = 0;
-
- if (dev->driver && dev->driver->resume)
- rc = dev->driver->resume(dev);
- return rc;
-}
-
static int i2c_device_probe(struct device *dev)
{
return -ENODEV;
@@ -75,15 +60,53 @@
return 0;
}
+static void i2c_device_shutdown(struct device *dev)
+{
+ struct i2c_driver *driver;
+
+ if (!dev->driver)
+ return;
+ driver = to_i2c_driver(dev->driver);
+ if (driver->shutdown)
+ driver->shutdown(to_i2c_client(dev));
+}
+
+static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
+{
+ struct i2c_driver *driver;
+
+ if (!dev->driver)
+ return 0;
+ driver = to_i2c_driver(dev->driver);
+ if (!driver->suspend)
+ return 0;
+ return driver->suspend(to_i2c_client(dev), mesg);
+}
+
+static int i2c_device_resume(struct device * dev)
+{
+ struct i2c_driver *driver;
+
+ if (!dev->driver)
+ return 0;
+ driver = to_i2c_driver(dev->driver);
+ if (!driver->resume)
+ return 0;
+ return driver->resume(to_i2c_client(dev));
+}
+
struct bus_type i2c_bus_type = {
- .name = "i2c",
- .match = i2c_device_match,
- .probe = i2c_device_probe,
- .remove = i2c_device_remove,
- .suspend = i2c_bus_suspend,
- .resume = i2c_bus_resume,
+ .name = "i2c",
+ .match = i2c_device_match,
+ .probe = i2c_device_probe,
+ .remove = i2c_device_remove,
+ .shutdown = i2c_device_shutdown,
+ .suspend = i2c_device_suspend,
+ .resume = i2c_device_resume,
};
+/* ------------------------------------------------------------------------- */
+
void i2c_adapter_dev_release(struct device *dev)
{
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);