i2c: Devices which have some i2c addr can work in same i2c bus

If i2c slave devices don't work at the same time, which have
the same i2c addr, this patch can make them working.

Change-Id: I1bfb7783924b08bdc6e12bf47c2de01bdac7c2e2
Signed-off-by: Zhang aihui <zah@rock-chips.com>
Signed-off-by: Wang Jie <dave.wang@rock-chips.com>
This commit is contained in:
Zhang aihui
2017-08-08 07:03:29 +00:00
committed by Tao Huang
parent 497e7bd6e1
commit 37fd8ed0a9

View File

@@ -60,6 +60,7 @@
static DEFINE_MUTEX(core_lock);
static DEFINE_IDR(i2c_adapter_idr);
static int i2c_check_addr_ex(struct i2c_adapter *adapter, int addr);
static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
static DEFINE_STATIC_KEY_FALSE(i2c_trace_msg_key);
@@ -805,7 +806,8 @@ static void i2c_adapter_unlock_bus(struct i2c_adapter *adapter,
static void i2c_dev_set_name(struct i2c_adapter *adap,
struct i2c_client *client,
struct i2c_board_info const *info)
struct i2c_board_info const *info,
int status)
{
struct acpi_device *adev = ACPI_COMPANION(&client->dev);
@@ -819,8 +821,12 @@ static void i2c_dev_set_name(struct i2c_adapter *adap,
return;
}
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
i2c_encode_flags_to_addr(client));
if (status == 0)
dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
i2c_encode_flags_to_addr(client));
else
dev_set_name(&client->dev, "%d-%04x-%01x", i2c_adapter_id(adap),
i2c_encode_flags_to_addr(client), status);
}
int i2c_dev_irq_from_resources(const struct resource *resources,
@@ -896,9 +902,11 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
}
/* Check for address business */
status = i2c_check_addr_busy(adap, i2c_encode_flags_to_addr(client));
status = i2c_check_addr_ex(adap, i2c_encode_flags_to_addr(client));
if (status)
goto out_err;
dev_err(&adap->dev,
"%d i2c clients have been registered at 0x%02x",
status, client->addr);
client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type;
@@ -906,7 +914,7 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
client->dev.of_node = of_node_get(info->of_node);
client->dev.fwnode = info->fwnode;
i2c_dev_set_name(adap, client, info);
i2c_dev_set_name(adap, client, info, status);
if (info->properties) {
status = device_add_properties(&client->dev, info->properties);
@@ -932,10 +940,6 @@ out_free_props:
device_remove_properties(&client->dev);
out_err_put_of_node:
of_node_put(info->of_node);
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 ERR_PTR(status);
@@ -1835,6 +1839,33 @@ EXPORT_SYMBOL(i2c_del_driver);
/* ------------------------------------------------------------------------- */
struct i2c_addr_cnt {
int addr;
int cnt;
};
static int __i2c_check_addr_ex(struct device *dev, void *addrp)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_addr_cnt *addrinfo = (struct i2c_addr_cnt *)addrp;
int addr = addrinfo->addr;
if (client && client->addr == addr)
addrinfo->cnt++;
return 0;
}
static int i2c_check_addr_ex(struct i2c_adapter *adapter, int addr)
{
struct i2c_addr_cnt addrinfo;
addrinfo.addr = addr;
addrinfo.cnt = 0;
device_for_each_child(&adapter->dev, &addrinfo, __i2c_check_addr_ex);
return addrinfo.cnt;
}
struct i2c_cmd_arg {
unsigned cmd;
void *arg;