EXPORT_SYMBOL_GPL(i2c_unregister_device);
+static int dummy_nop(struct i2c_client *client)
+{
+ return 0;
+}
+
+static struct i2c_driver dummy_driver = {
+ .driver.name = "dummy",
+ .probe = dummy_nop,
+ .remove = dummy_nop,
+};
+
+/**
+ * i2c_new_dummy - return a new i2c device bound to a dummy driver
+ * @adapter: the adapter managing the device
+ * @address: seven bit address to be used
+ * @type: optional label used for i2c_client.name
+ * Context: can sleep
+ *
+ * This returns an I2C client bound to the "dummy" driver, intended for use
+ * with devices that consume multiple addresses. Examples of such chips
+ * include various EEPROMS (like 24c04 and 24c08 models).
+ *
+ * These dummy devices have two main uses. First, most I2C and SMBus calls
+ * except i2c_transfer() need a client handle; the dummy will be that handle.
+ * And second, this prevents the specified address from being bound to a
+ * different driver.
+ *
+ * This returns the new i2c client, which should be saved for later use with
+ * i2c_unregister_device(); or NULL to indicate an error.
+ */
+struct i2c_client *
+i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type)
+{
+ struct i2c_board_info info = {
+ .driver_name = "dummy",
+ .addr = address,
+ };
+
+ if (type)
+ strlcpy(info.type, type, sizeof info.type);
+ return i2c_new_device(adapter, &info);
+}
+EXPORT_SYMBOL_GPL(i2c_new_dummy);
+
/* ------------------------------------------------------------------------- */
/* I2C bus adapters -- one roots each I2C or SMBUS segment */
struct i2c_adapter *adapter = client->adapter;
int res = 0;
- mutex_lock(&adapter->clist_lock);
- if (i2c_check_addr(client->adapter, client->addr)) {
- res = -EBUSY;
- goto out_unlock;
- }
- list_add_tail(&client->list,&adapter->clients);
-
client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type;
snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
"%d-%04x", i2c_adapter_id(adapter), client->addr);
- dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
- client->name, client->dev.bus_id);
res = device_register(&client->dev);
if (res)
- goto out_list;
+ goto out_err;
+
+ mutex_lock(&adapter->clist_lock);
+ list_add_tail(&client->list, &adapter->clients);
mutex_unlock(&adapter->clist_lock);
+ dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+ client->name, client->dev.bus_id);
+
if (adapter->client_register) {
if (adapter->client_register(client)) {
dev_dbg(&adapter->dev, "client_register "
return 0;
-out_list:
- list_del(&client->list);
+out_err:
dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
"(%d)\n", client->name, client->addr, res);
-out_unlock:
- mutex_unlock(&adapter->clist_lock);
return res;
}
EXPORT_SYMBOL(i2c_attach_client);
mutex_lock(&adapter->clist_lock);
list_del(&client->list);
+ mutex_unlock(&adapter->clist_lock);
+
init_completion(&client->released);
device_unregister(&client->dev);
- mutex_unlock(&adapter->clist_lock);
wait_for_completion(&client->released);
out:
retval = bus_register(&i2c_bus_type);
if (retval)
return retval;
- return class_register(&i2c_adapter_class);
+ retval = class_register(&i2c_adapter_class);
+ if (retval)
+ goto bus_err;
+ retval = i2c_add_driver(&dummy_driver);
+ if (retval)
+ goto class_err;
+ return 0;
+
+class_err:
+ class_unregister(&i2c_adapter_class);
+bus_err:
+ bus_unregister(&i2c_bus_type);
+ return retval;
}
static void __exit i2c_exit(void)
{
+ i2c_del_driver(&dummy_driver);
class_unregister(&i2c_adapter_class);
bus_unregister(&i2c_bus_type);
}
return NULL;
}
- mutex_lock(&adap->clist_lock);
for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) {
/* Check address validity */
if (addr_list[i] < 0x03 || addr_list[i] > 0x77) {
break;
}
}
- mutex_unlock(&adap->clist_lock);
if (addr_list[i] == I2C_CLIENT_END) {
dev_dbg(&adap->dev, "Probing failed, no device found\n");