Commit 99cd8e25875a109455b709b5a41d4891b8d8e58e

Authored by Jean Delvare
1 parent 35fc37f818

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>

Showing 3 changed files with 168 additions and 2 deletions Side-by-side Diff

Documentation/i2c/instantiating-devices
... ... @@ -165,4 +165,48 @@
165 165 Once again, method 3 should be avoided wherever possible. Explicit device
166 166 instantiation (methods 1 and 2) is much preferred for it is safer and
167 167 faster.
  168 +
  169 +
  170 +Method 4: Instantiate from user-space
  171 +-------------------------------------
  172 +
  173 +In general, the kernel should know which I2C devices are connected and
  174 +what addresses they live at. However, in certain cases, it does not, so a
  175 +sysfs interface was added to let the user provide the information. This
  176 +interface is made of 2 attribute files which are created in every I2C bus
  177 +directory: new_device and delete_device. Both files are write only and you
  178 +must write the right parameters to them in order to properly instantiate,
  179 +respectively delete, an I2C device.
  180 +
  181 +File new_device takes 2 parameters: the name of the I2C device (a string)
  182 +and the address of the I2C device (a number, typically expressed in
  183 +hexadecimal starting with 0x, but can also be expressed in decimal.)
  184 +
  185 +File delete_device takes a single parameter: the address of the I2C
  186 +device. As no two devices can live at the same address on a given I2C
  187 +segment, the address is sufficient to uniquely identify the device to be
  188 +deleted.
  189 +
  190 +Example:
  191 +# echo eeprom 0x50 > /sys/class/i2c-adapter/i2c-3/new_device
  192 +
  193 +While this interface should only be used when in-kernel device declaration
  194 +can'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 +
  206 +This interface is a replacement for the force_* module parameters some I2C
  207 +drivers implement. Being implemented in i2c-core rather than in each
  208 +device driver individually, it is much more efficient, and also has the
  209 +advantage that you do not have to reload the driver to change a setting.
  210 +You can also instantiate the device before the driver is loaded or even
  211 +available, and you don't need to know what driver the device needs.
drivers/i2c/i2c-core.c
... ... @@ -38,11 +38,12 @@
38 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 42 that device detection, deletion of detected devices, and attach_adapter
43 43 and detach_adapter calls are serialized */
44 44 static DEFINE_MUTEX(core_lock);
45 45 static DEFINE_IDR(i2c_adapter_idr);
  46 +static LIST_HEAD(userspace_devices);
46 47  
47 48 static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
48 49 static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
49 50  
... ... @@ -373,8 +374,128 @@
373 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 + */
  387 +static ssize_t
  388 +i2c_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 + */
  452 +static ssize_t
  453 +i2c_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 +
376 495 static struct device_attribute i2c_adapter_attrs[] = {
377 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  
... ... @@ -178,7 +178,8 @@
178 178 * @driver: device's driver, hence pointer to access routines
179 179 * @dev: Driver model device node for the slave.
180 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 184 * An i2c_client identifies a single device (i.e. chip) connected to an
184 185 * i2c bus. The behaviour exposed to Linux is defined by the driver