aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2007-02-13 16:09:00 -0500
committerJean Delvare <khali@arrakis.delvare>2007-02-13 16:09:00 -0500
commitf37dd80ac2a67e4e4e921f99d34a1ceeb2488abb (patch)
treec845e39b24feac331a9a67d49e0b8061f52131b3
parentb8d6f45b32f6fe72bf7304183275e99332544ce1 (diff)
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>
-rw-r--r--Documentation/i2c/porting-clients6
-rw-r--r--Documentation/i2c/writing-clients58
-rw-r--r--drivers/i2c/i2c-core.c65
-rw-r--r--include/linux/i2c.h7
4 files changed, 105 insertions, 31 deletions
diff --git a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
index f03c2a02f806..ca272b263a92 100644
--- a/Documentation/i2c/porting-clients
+++ b/Documentation/i2c/porting-clients
@@ -129,6 +129,12 @@ Technical changes:
129 structure, those name member should be initialized to a driver name 129 structure, those name member should be initialized to a driver name
130 string. i2c_driver itself has no name member anymore. 130 string. i2c_driver itself has no name member anymore.
131 131
132* [Driver model] Instead of shutdown or reboot notifiers, provide a
133 shutdown() method in your driver.
134
135* [Power management] Use the driver model suspend() and resume()
136 callbacks instead of the obsolete pm_register() calls.
137
132Coding policy: 138Coding policy:
133 139
134* [Copyright] Use (C), not (c), for copyright. 140* [Copyright] Use (C), not (c), for copyright.
diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
index 3a057c8e5507..fbcff96f4ca1 100644
--- a/Documentation/i2c/writing-clients
+++ b/Documentation/i2c/writing-clients
@@ -21,20 +21,26 @@ The driver structure
21 21
22Usually, you will implement a single driver structure, and instantiate 22Usually, you will implement a single driver structure, and instantiate
23all clients from it. Remember, a driver structure contains general access 23all clients from it. Remember, a driver structure contains general access
24routines, a client structure specific information like the actual I2C 24routines, and should be zero-initialized except for fields with data you
25address. 25provide. A client structure holds device-specific information like the
26driver model device node, and its I2C address.
26 27
27static struct i2c_driver foo_driver = { 28static struct i2c_driver foo_driver = {
28 .driver = { 29 .driver = {
29 .name = "foo", 30 .name = "foo",
30 }, 31 },
31 .attach_adapter = &foo_attach_adapter, 32 .attach_adapter = foo_attach_adapter,
32 .detach_client = &foo_detach_client, 33 .detach_client = foo_detach_client,
33 .command = &foo_command /* may be NULL */ 34 .shutdown = foo_shutdown, /* optional */
35 .suspend = foo_suspend, /* optional */
36 .resume = foo_resume, /* optional */
37 .command = foo_command, /* optional */
34} 38}
35 39
36The name field must match the driver name, including the case. It must not 40The name field is the driver name, and must not contain spaces. It
37contain spaces, and may be up to 31 characters long. 41should match the module name (if the driver can be compiled as a module),
42although you can use MODULE_ALIAS (passing "foo" in this example) to add
43another name for the module.
38 44
39All other fields are for call-back functions which will be explained 45All other fields are for call-back functions which will be explained
40below. 46below.
@@ -43,11 +49,18 @@ below.
43Extra client data 49Extra client data
44================= 50=================
45 51
46The client structure has a special `data' field that can point to any 52Each client structure has a special `data' field that can point to any
47structure at all. You can use this to keep client-specific data. You 53structure at all. You should use this to keep device-specific data,
54especially in drivers that handle multiple I2C or SMBUS devices. You
48do not always need this, but especially for `sensors' drivers, it can 55do not always need this, but especially for `sensors' drivers, it can
49be very useful. 56be very useful.
50 57
58 /* store the value */
59 void i2c_set_clientdata(struct i2c_client *client, void *data);
60
61 /* retrieve the value */
62 void *i2c_get_clientdata(struct i2c_client *client);
63
51An example structure is below. 64An example structure is below.
52 65
53 struct foo_data { 66 struct foo_data {
@@ -493,6 +506,33 @@ by `__init_data'. Hose functions and structures can be removed after
493kernel booting (or module loading) is completed. 506kernel booting (or module loading) is completed.
494 507
495 508
509Power Management
510================
511
512If your I2C device needs special handling when entering a system low
513power state -- like putting a transceiver into a low power mode, or
514activating a system wakeup mechanism -- do that in the suspend() method.
515The resume() method should reverse what the suspend() method does.
516
517These are standard driver model calls, and they work just like they
518would for any other driver stack. The calls can sleep, and can use
519I2C messaging to the device being suspended or resumed (since their
520parent I2C adapter is active when these calls are issued, and IRQs
521are still enabled).
522
523
524System Shutdown
525===============
526
527If your I2C device needs special handling when the system shuts down
528or reboots (including kexec) -- like turning something off -- use a
529shutdown() method.
530
531Again, this is a standard driver model call, working just like it
532would for any other driver stack: the calls can sleep, and can use
533I2C messaging.
534
535
496Command function 536Command function
497================ 537================
498 538
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 60f6eb194046..9653f7f81561 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -41,49 +41,72 @@ static LIST_HEAD(drivers);
41static DEFINE_MUTEX(core_lists); 41static DEFINE_MUTEX(core_lists);
42static DEFINE_IDR(i2c_adapter_idr); 42static DEFINE_IDR(i2c_adapter_idr);
43 43
44
45/* ------------------------------------------------------------------------- */
46
44/* match always succeeds, as we want the probe() to tell if we really accept this match */ 47/* match always succeeds, as we want the probe() to tell if we really accept this match */
45static int i2c_device_match(struct device *dev, struct device_driver *drv) 48static int i2c_device_match(struct device *dev, struct device_driver *drv)
46{ 49{
47 return 1; 50 return 1;
48} 51}
49 52
50static int i2c_bus_suspend(struct device * dev, pm_message_t state) 53static int i2c_device_probe(struct device *dev)
51{ 54{
52 int rc = 0; 55 return -ENODEV;
56}
53 57
54 if (dev->driver && dev->driver->suspend) 58static int i2c_device_remove(struct device *dev)
55 rc = dev->driver->suspend(dev, state); 59{
56 return rc; 60 return 0;
57} 61}
58 62
59static int i2c_bus_resume(struct device * dev) 63static void i2c_device_shutdown(struct device *dev)
60{ 64{
61 int rc = 0; 65 struct i2c_driver *driver;
62 66
63 if (dev->driver && dev->driver->resume) 67 if (!dev->driver)
64 rc = dev->driver->resume(dev); 68 return;
65 return rc; 69 driver = to_i2c_driver(dev->driver);
70 if (driver->shutdown)
71 driver->shutdown(to_i2c_client(dev));
66} 72}
67 73
68static int i2c_device_probe(struct device *dev) 74static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
69{ 75{
70 return -ENODEV; 76 struct i2c_driver *driver;
77
78 if (!dev->driver)
79 return 0;
80 driver = to_i2c_driver(dev->driver);
81 if (!driver->suspend)
82 return 0;
83 return driver->suspend(to_i2c_client(dev), mesg);
71} 84}
72 85
73static int i2c_device_remove(struct device *dev) 86static int i2c_device_resume(struct device * dev)
74{ 87{
75 return 0; 88 struct i2c_driver *driver;
89
90 if (!dev->driver)
91 return 0;
92 driver = to_i2c_driver(dev->driver);
93 if (!driver->resume)
94 return 0;
95 return driver->resume(to_i2c_client(dev));
76} 96}
77 97
78struct bus_type i2c_bus_type = { 98struct bus_type i2c_bus_type = {
79 .name = "i2c", 99 .name = "i2c",
80 .match = i2c_device_match, 100 .match = i2c_device_match,
81 .probe = i2c_device_probe, 101 .probe = i2c_device_probe,
82 .remove = i2c_device_remove, 102 .remove = i2c_device_remove,
83 .suspend = i2c_bus_suspend, 103 .shutdown = i2c_device_shutdown,
84 .resume = i2c_bus_resume, 104 .suspend = i2c_device_suspend,
105 .resume = i2c_device_resume,
85}; 106};
86 107
108/* ------------------------------------------------------------------------- */
109
87void i2c_adapter_dev_release(struct device *dev) 110void i2c_adapter_dev_release(struct device *dev)
88{ 111{
89 struct i2c_adapter *adap = dev_to_i2c_adapter(dev); 112 struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 71e50d3e492f..9428092017e3 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -125,7 +125,12 @@ struct i2c_driver {
125 * it must be freed here. 125 * it must be freed here.
126 */ 126 */
127 int (*detach_client)(struct i2c_client *); 127 int (*detach_client)(struct i2c_client *);
128 128
129 /* driver model interfaces that don't relate to enumeration */
130 void (*shutdown)(struct i2c_client *);
131 int (*suspend)(struct i2c_client *, pm_message_t mesg);
132 int (*resume)(struct i2c_client *);
133
129 /* a ioctl like command that can be used to perform specific functions 134 /* a ioctl like command that can be used to perform specific functions
130 * with the device. 135 * with the device.
131 */ 136 */