Split existing API i2c_new_device(), i2c_new_probed_device() into two halves. The first half creates new i2c devices and the second half calls device_register(). It allows additional work to be done before registering the device. Signed-off-by: York Sun <yorksun@xxxxxxxxxxxxx> CC: Wolfram Sang <wsa@xxxxxxxxxxxxx> CC: Stephen Boyd <sboyd@xxxxxxxxxxxxxx> Suggested-by: Stephen Boyd <sboyd@xxxxxxxxxxxxxx> --- drivers/i2c/i2c-core.c | 96 ++++++++++++++++++++++++++++++++++++++---------- include/linux/i2c.h | 8 ++++ 2 files changed, 85 insertions(+), 19 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 5f89f1e..ff941b8 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -980,23 +980,19 @@ static void i2c_dev_set_name(struct i2c_adapter *adap, } /** - * i2c_new_device - instantiate an i2c device + * i2c_new_device_unregistered -- instantiate an i2c device unregistered * @adap: the adapter managing the device * @info: describes one I2C device; bus_num is ignored * Context: can sleep * - * Create an i2c device. Binding is handled through driver model - * probe()/remove() methods. A driver may be bound to this device when we - * return from this function, or any later moment (e.g. maybe hotplugging will - * load the driver module). This call is not appropriate for use by mainboard - * initialization logic, which usually runs during an arch_initcall() long - * before any i2c_adapter could exist. + * Create an i2c device but leave it unregistered. * * This returns the new i2c client, which may be saved for later use with - * i2c_unregister_device(); or NULL to indicate an error. + * device_register() or i2c_unregister_device(); or NULL to indicate an error. */ struct i2c_client * -i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) +i2c_new_device_unregistered(struct i2c_adapter *adap, + struct i2c_board_info const *info) { struct i2c_client *client; int status; @@ -1022,13 +1018,16 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) if (status) { dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n", client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); - goto out_err_silent; + goto out_err; } /* Check for address business */ status = i2c_check_addr_busy(adap, i2c_encode_flags_to_addr(client)); - if (status) + if (status) { + dev_err(&adap->dev, "i2c client %s at 0x%02x busy\n", + client->name, client->addr); goto out_err; + } client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; @@ -1037,6 +1036,41 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.fwnode = info->fwnode; i2c_dev_set_name(adap, client); + + return client; + +out_err: + kfree(client); + return NULL; +} +EXPORT_SYMBOL_GPL(i2c_new_device_unregistered); + +/** + * i2c_new_device - instantiate an i2c device + * @adap: the adapter managing the device + * @info: describes one I2C device; bus_num is ignored + * Context: can sleep + * + * Create an i2c device. Binding is handled through driver model + * probe()/remove() methods. A driver may be bound to this device when we + * return from this function, or any later moment (e.g. maybe hotplugging will + * load the driver module). This call is not appropriate for use by mainboard + * initialization logic, which usually runs during an arch_initcall() long + * before any i2c_adapter could exist. + * + * This returns the new i2c client, which may be saved for later use with + * i2c_unregister_device(); or NULL to indicate an error. + */ +struct i2c_client * +i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) +{ + struct i2c_client *client; + int status; + + client = i2c_new_device_unregistered(adap, info); + if (!client) + goto out_err_silent; + status = device_register(&client->dev); if (status) goto out_err; @@ -1050,7 +1084,6 @@ out_err: dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " "(%d)\n", client->name, client->addr, status); out_err_silent: - kfree(client); return NULL; } EXPORT_SYMBOL_GPL(i2c_new_device); @@ -2455,11 +2488,9 @@ int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) } EXPORT_SYMBOL_GPL(i2c_probe_func_quick_read); -struct i2c_client * -i2c_new_probed_device(struct i2c_adapter *adap, - struct i2c_board_info *info, - unsigned short const *addr_list, - int (*probe)(struct i2c_adapter *, unsigned short addr)) +static unsigned short address_probe(struct i2c_adapter *adap, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)) { int i; @@ -2486,12 +2517,39 @@ i2c_new_probed_device(struct i2c_adapter *adap, break; } - if (addr_list[i] == I2C_CLIENT_END) { + return addr_list[i]; +} + +struct i2c_client * +i2c_new_probed_device_unregistered(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)) +{ + info->addr = address_probe(adap, addr_list, probe); + + if (info->addr == I2C_CLIENT_END) { + dev_dbg(&adap->dev, "Probing failed, no device found\n"); + return NULL; + } + + return i2c_new_device_unregistered(adap, info); +} +EXPORT_SYMBOL_GPL(i2c_new_probed_device_unregistered); + +struct i2c_client * +i2c_new_probed_device(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)) +{ + info->addr = address_probe(adap, addr_list, probe); + + if (info->addr == I2C_CLIENT_END) { dev_dbg(&adap->dev, "Probing failed, no device found\n"); return NULL; } - info->addr = addr_list[i]; return i2c_new_device(adap, info); } EXPORT_SYMBOL_GPL(i2c_new_probed_device); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 768063b..85068ae 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -327,6 +327,9 @@ struct i2c_board_info { */ extern struct i2c_client * i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info); +extern struct i2c_client * +i2c_new_device_unregistered(struct i2c_adapter *adap, + struct i2c_board_info const *info); /* If you don't know the exact address of an I2C device, use this variant * instead, which can probe for device presence in a list of possible @@ -339,6 +342,11 @@ i2c_new_probed_device(struct i2c_adapter *adap, struct i2c_board_info *info, unsigned short const *addr_list, int (*probe)(struct i2c_adapter *, unsigned short addr)); +extern struct i2c_client * +i2c_new_probed_device_unregistered(struct i2c_adapter *adap, + struct i2c_board_info *info, + unsigned short const *addr_list, + int (*probe)(struct i2c_adapter *, unsigned short addr)); /* Common custom probe functions */ extern int i2c_probe_func_quick_read(struct i2c_adapter *, unsigned short addr); -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html