mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 11:50:43 +09:00
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:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user