diff options
-rw-r--r-- | drivers/i2c/i2c-core.c | 59 | ||||
-rw-r--r-- | include/linux/i2c.h | 6 |
2 files changed, 64 insertions, 1 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index cd3fcb85ca7f..96da22e9a5a4 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -296,6 +296,50 @@ void i2c_unregister_device(struct i2c_client *client) | |||
296 | EXPORT_SYMBOL_GPL(i2c_unregister_device); | 296 | EXPORT_SYMBOL_GPL(i2c_unregister_device); |
297 | 297 | ||
298 | 298 | ||
299 | static int dummy_nop(struct i2c_client *client) | ||
300 | { | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static struct i2c_driver dummy_driver = { | ||
305 | .driver.name = "dummy", | ||
306 | .probe = dummy_nop, | ||
307 | .remove = dummy_nop, | ||
308 | }; | ||
309 | |||
310 | /** | ||
311 | * i2c_new_dummy - return a new i2c device bound to a dummy driver | ||
312 | * @adapter: the adapter managing the device | ||
313 | * @address: seven bit address to be used | ||
314 | * @type: optional label used for i2c_client.name | ||
315 | * Context: can sleep | ||
316 | * | ||
317 | * This returns an I2C client bound to the "dummy" driver, intended for use | ||
318 | * with devices that consume multiple addresses. Examples of such chips | ||
319 | * include various EEPROMS (like 24c04 and 24c08 models). | ||
320 | * | ||
321 | * These dummy devices have two main uses. First, most I2C and SMBus calls | ||
322 | * except i2c_transfer() need a client handle; the dummy will be that handle. | ||
323 | * And second, this prevents the specified address from being bound to a | ||
324 | * different driver. | ||
325 | * | ||
326 | * This returns the new i2c client, which should be saved for later use with | ||
327 | * i2c_unregister_device(); or NULL to indicate an error. | ||
328 | */ | ||
329 | struct i2c_client * | ||
330 | i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type) | ||
331 | { | ||
332 | struct i2c_board_info info = { | ||
333 | .driver_name = "dummy", | ||
334 | .addr = address, | ||
335 | }; | ||
336 | |||
337 | if (type) | ||
338 | strlcpy(info.type, type, sizeof info.type); | ||
339 | return i2c_new_device(adapter, &info); | ||
340 | } | ||
341 | EXPORT_SYMBOL_GPL(i2c_new_dummy); | ||
342 | |||
299 | /* ------------------------------------------------------------------------- */ | 343 | /* ------------------------------------------------------------------------- */ |
300 | 344 | ||
301 | /* I2C bus adapters -- one roots each I2C or SMBUS segment */ | 345 | /* I2C bus adapters -- one roots each I2C or SMBUS segment */ |
@@ -841,11 +885,24 @@ static int __init i2c_init(void) | |||
841 | retval = bus_register(&i2c_bus_type); | 885 | retval = bus_register(&i2c_bus_type); |
842 | if (retval) | 886 | if (retval) |
843 | return retval; | 887 | return retval; |
844 | return class_register(&i2c_adapter_class); | 888 | retval = class_register(&i2c_adapter_class); |
889 | if (retval) | ||
890 | goto bus_err; | ||
891 | retval = i2c_add_driver(&dummy_driver); | ||
892 | if (retval) | ||
893 | goto class_err; | ||
894 | return 0; | ||
895 | |||
896 | class_err: | ||
897 | class_unregister(&i2c_adapter_class); | ||
898 | bus_err: | ||
899 | bus_unregister(&i2c_bus_type); | ||
900 | return retval; | ||
845 | } | 901 | } |
846 | 902 | ||
847 | static void __exit i2c_exit(void) | 903 | static void __exit i2c_exit(void) |
848 | { | 904 | { |
905 | i2c_del_driver(&dummy_driver); | ||
849 | class_unregister(&i2c_adapter_class); | 906 | class_unregister(&i2c_adapter_class); |
850 | bus_unregister(&i2c_bus_type); | 907 | bus_unregister(&i2c_bus_type); |
851 | } | 908 | } |
diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 731928ae972c..76014f8f3c60 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h | |||
@@ -259,6 +259,12 @@ i2c_new_probed_device(struct i2c_adapter *adap, | |||
259 | struct i2c_board_info *info, | 259 | struct i2c_board_info *info, |
260 | unsigned short const *addr_list); | 260 | unsigned short const *addr_list); |
261 | 261 | ||
262 | /* For devices that use several addresses, use i2c_new_dummy() to make | ||
263 | * client handles for the extra addresses. | ||
264 | */ | ||
265 | extern struct i2c_client * | ||
266 | i2c_new_dummy(struct i2c_adapter *adap, u16 address, const char *type); | ||
267 | |||
262 | extern void i2c_unregister_device(struct i2c_client *); | 268 | extern void i2c_unregister_device(struct i2c_client *); |
263 | 269 | ||
264 | /* Mainboard arch_initcall() code should register all its I2C devices. | 270 | /* Mainboard arch_initcall() code should register all its I2C devices. |