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>
This commit is contained in:
zah
2017-08-08 07:03:29 +00:00
committed by Tao Huang
parent 0dbdb29de2
commit b97a325b33

View File

@@ -67,6 +67,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);
@@ -666,7 +667,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);
@@ -680,8 +682,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);
}
static int i2c_dev_irq_from_resources(const struct resource *resources,
@@ -757,7 +763,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
}
/* 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;
@@ -767,7 +773,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
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);
@@ -1650,6 +1656,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;
}
/**
* i2c_use_client - increments the reference count of the i2c client structure
* @client: the client being referenced