aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-06-19 10:58:20 -0400
committerJean Delvare <khali@linux-fr.org>2009-06-19 10:58:20 -0400
commit99cd8e25875a109455b709b5a41d4891b8d8e58e (patch)
tree38907f3c6df0048ce0c4764a282c4a21c74aa49f
parent35fc37f8188177e3ba3e7f99a6e3300e490e9181 (diff)
i2c: Add a sysfs interface to instantiate devices
Add a sysfs interface to instantiate and delete I2C devices. This is primarily a replacement of the force_* module parameters implemented by some i2c drivers. These module parameters were implemented internally by the I2C_CLIENT_INSMOD* macros, which don't scale well. This can also be used when developing a driver on a self-soldered board which doesn't yet have proper I2C device declaration at the platform level, and presumably for various debugging situations. Signed-off-by: Jean Delvare <khali@linux-fr.org> Cc: David Brownell <dbrownell@users.sourceforge.net>
-rw-r--r--Documentation/i2c/instantiating-devices44
-rw-r--r--drivers/i2c/i2c-core.c123
-rw-r--r--include/linux/i2c.h3
3 files changed, 168 insertions, 2 deletions
diff --git a/Documentation/i2c/instantiating-devices b/Documentation/i2c/instantiating-devices
index b55ce57a84d..c740b7b4108 100644
--- a/Documentation/i2c/instantiating-devices
+++ b/Documentation/i2c/instantiating-devices
@@ -165,3 +165,47 @@ was done there. Two significant differences are:
165Once again, method 3 should be avoided wherever possible. Explicit device 165Once again, method 3 should be avoided wherever possible. Explicit device
166instantiation (methods 1 and 2) is much preferred for it is safer and 166instantiation (methods 1 and 2) is much preferred for it is safer and
167faster. 167faster.
168
169
170Method 4: Instantiate from user-space
171-------------------------------------
172
173In general, the kernel should know which I2C devices are connected and
174what addresses they live at. However, in certain cases, it does not, so a
175sysfs interface was added to let the user provide the information. This
176interface is made of 2 attribute files which are created in every I2C bus
177directory: new_device and delete_device. Both files are write only and you
178must write the right parameters to them in order to properly instantiate,
179respectively delete, an I2C device.
180
181File new_device takes 2 parameters: the name of the I2C device (a string)
182and the address of the I2C device (a number, typically expressed in
183hexadecimal starting with 0x, but can also be expressed in decimal.)
184
185File delete_device takes a single parameter: the address of the I2C
186device. As no two devices can live at the same address on a given I2C
187segment, the address is sufficient to uniquely identify the device to be
188deleted.
189
190Example:
191# echo eeprom 0x50 > /sys/class/i2c-adapter/i2c-3/new_device
192
193While this interface should only be used when in-kernel device declaration
194can't be done, there is a variety of cases where it can be helpful:
195* The I2C driver usually detects devices (method 3 above) but the bus
196 segment your device lives on doesn't have the proper class bit set and
197 thus detection doesn't trigger.
198* The I2C driver usually detects devices, but your device lives at an
199 unexpected address.
200* The I2C driver usually detects devices, but your device is not detected,
201 either because the detection routine is too strict, or because your
202 device is not officially supported yet but you know it is compatible.
203* You are developing a driver on a test board, where you soldered the I2C
204 device yourself.
205
206This interface is a replacement for the force_* module parameters some I2C
207drivers implement. Being implemented in i2c-core rather than in each
208device driver individually, it is much more efficient, and also has the
209advantage that you do not have to reload the driver to change a setting.
210You can also instantiate the device before the driver is loaded or even
211available, and you don't need to know what driver the device needs.
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index a2f1cd3766f..eb084fa0df8 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -38,11 +38,12 @@
38#include "i2c-core.h" 38#include "i2c-core.h"
39 39
40 40
41/* core_lock protects i2c_adapter_idr, and guarantees 41/* core_lock protects i2c_adapter_idr, userspace_devices, and guarantees
42 that device detection, deletion of detected devices, and attach_adapter 42 that device detection, deletion of detected devices, and attach_adapter
43 and detach_adapter calls are serialized */ 43 and detach_adapter calls are serialized */
44static DEFINE_MUTEX(core_lock); 44static DEFINE_MUTEX(core_lock);
45static DEFINE_IDR(i2c_adapter_idr); 45static DEFINE_IDR(i2c_adapter_idr);
46static LIST_HEAD(userspace_devices);
46 47
47static int i2c_check_addr(struct i2c_adapter *adapter, int addr); 48static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
48static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); 49static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
@@ -373,8 +374,128 @@ show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
373 return sprintf(buf, "%s\n", adap->name); 374 return sprintf(buf, "%s\n", adap->name);
374} 375}
375 376
377/*
378 * Let users instantiate I2C devices through sysfs. This can be used when
379 * platform initialization code doesn't contain the proper data for
380 * whatever reason. Also useful for drivers that do device detection and
381 * detection fails, either because the device uses an unexpected address,
382 * or this is a compatible device with different ID register values.
383 *
384 * Parameter checking may look overzealous, but we really don't want
385 * the user to provide incorrect parameters.
386 */
387static ssize_t
388i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr,
389 const char *buf, size_t count)
390{
391 struct i2c_adapter *adap = to_i2c_adapter(dev);
392 struct i2c_board_info info;
393 struct i2c_client *client;
394 char *blank, end;
395 int res;
396
397 dev_warn(dev, "The new_device interface is still experimental "
398 "and may change in a near future\n");
399 memset(&info, 0, sizeof(struct i2c_board_info));
400
401 blank = strchr(buf, ' ');
402 if (!blank) {
403 dev_err(dev, "%s: Missing parameters\n", "new_device");
404 return -EINVAL;
405 }
406 if (blank - buf > I2C_NAME_SIZE - 1) {
407 dev_err(dev, "%s: Invalid device name\n", "new_device");
408 return -EINVAL;
409 }
410 memcpy(info.type, buf, blank - buf);
411
412 /* Parse remaining parameters, reject extra parameters */
413 res = sscanf(++blank, "%hi%c", &info.addr, &end);
414 if (res < 1) {
415 dev_err(dev, "%s: Can't parse I2C address\n", "new_device");
416 return -EINVAL;
417 }
418 if (res > 1 && end != '\n') {
419 dev_err(dev, "%s: Extra parameters\n", "new_device");
420 return -EINVAL;
421 }
422
423 if (info.addr < 0x03 || info.addr > 0x77) {
424 dev_err(dev, "%s: Invalid I2C address 0x%hx\n", "new_device",
425 info.addr);
426 return -EINVAL;
427 }
428
429 client = i2c_new_device(adap, &info);
430 if (!client)
431 return -EEXIST;
432
433 /* Keep track of the added device */
434 mutex_lock(&core_lock);
435 list_add_tail(&client->detected, &userspace_devices);
436 mutex_unlock(&core_lock);
437 dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device",
438 info.type, info.addr);
439
440 return count;
441}
442
443/*
444 * And of course let the users delete the devices they instantiated, if
445 * they got it wrong. This interface can only be used to delete devices
446 * instantiated by i2c_sysfs_new_device above. This guarantees that we
447 * don't delete devices to which some kernel code still has references.
448 *
449 * Parameter checking may look overzealous, but we really don't want
450 * the user to delete the wrong device.
451 */
452static ssize_t
453i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
454 const char *buf, size_t count)
455{
456 struct i2c_adapter *adap = to_i2c_adapter(dev);
457 struct i2c_client *client, *next;
458 unsigned short addr;
459 char end;
460 int res;
461
462 /* Parse parameters, reject extra parameters */
463 res = sscanf(buf, "%hi%c", &addr, &end);
464 if (res < 1) {
465 dev_err(dev, "%s: Can't parse I2C address\n", "delete_device");
466 return -EINVAL;
467 }
468 if (res > 1 && end != '\n') {
469 dev_err(dev, "%s: Extra parameters\n", "delete_device");
470 return -EINVAL;
471 }
472
473 /* Make sure the device was added through sysfs */
474 res = -ENOENT;
475 mutex_lock(&core_lock);
476 list_for_each_entry_safe(client, next, &userspace_devices, detected) {
477 if (client->addr == addr && client->adapter == adap) {
478 dev_info(dev, "%s: Deleting device %s at 0x%02hx\n",
479 "delete_device", client->name, client->addr);
480
481 list_del(&client->detected);
482 i2c_unregister_device(client);
483 res = count;
484 break;
485 }
486 }
487 mutex_unlock(&core_lock);
488
489 if (res < 0)
490 dev_err(dev, "%s: Can't find device in list\n",
491 "delete_device");
492 return res;
493}
494
376static struct device_attribute i2c_adapter_attrs[] = { 495static struct device_attribute i2c_adapter_attrs[] = {
377 __ATTR(name, S_IRUGO, show_adapter_name, NULL), 496 __ATTR(name, S_IRUGO, show_adapter_name, NULL),
497 __ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device),
498 __ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device),
378 { }, 499 { },
379}; 500};
380 501
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 5f8157610c6..844d2662a87 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -178,7 +178,8 @@ struct i2c_driver {
178 * @driver: device's driver, hence pointer to access routines 178 * @driver: device's driver, hence pointer to access routines
179 * @dev: Driver model device node for the slave. 179 * @dev: Driver model device node for the slave.
180 * @irq: indicates the IRQ generated by this device (if any) 180 * @irq: indicates the IRQ generated by this device (if any)
181 * @detected: member of an i2c_driver.clients list 181 * @detected: member of an i2c_driver.clients list or i2c-core's
182 * userspace_devices list
182 * 183 *
183 * An i2c_client identifies a single device (i.e. chip) connected to an 184 * An i2c_client identifies a single device (i.e. chip) connected to an
184 * i2c bus. The behaviour exposed to Linux is defined by the driver 185 * i2c bus. The behaviour exposed to Linux is defined by the driver