i2c: fix devices which have same i2c addr can't work together in same i2c bus
authorddl <ddl@rockchip.com>
Mon, 11 Apr 2011 11:23:41 +0000 (19:23 +0800)
committerddl <ddl@rockchip.com>
Mon, 11 Apr 2011 11:24:39 +0000 (19:24 +0800)
drivers/i2c/i2c-core.c

index 27919cd1709510e1f87dd2875ed0cfd78ca85e88..267515e6ce9e3195477c1628e8fe5056c0352402 100755 (executable)
@@ -48,6 +48,7 @@ static LIST_HEAD(userspace_devices);
 
 static struct device_type i2c_client_type;
 static int i2c_check_addr(struct i2c_adapter *adapter, int addr);
+static int i2c_check_addr_ex(struct i2c_adapter *adapter, int addr);
 static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
 
 /* ------------------------------------------------------------------------- */
@@ -300,16 +301,34 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
        strlcpy(client->name, info->type, sizeof(client->name));
 
        /* Check for address business */
+    #if 0
        status = i2c_check_addr(adap, client->addr);
        if (status)
                goto out_err;
+    #else
+    /* ddl@rock-chips.com : Devices which have some i2c addr can work in same i2c bus, 
+      if devices havn't work at the same time.*/
+    status = i2c_check_addr_ex(adap, client->addr);
+    #endif
 
        client->dev.parent = &client->adapter->dev;
        client->dev.bus = &i2c_bus_type;
        client->dev.type = &i2c_client_type;
 
-       dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
-                    client->addr);
+    /* ddl@rock-chips.com : Devices which have some i2c addr can work in same i2c bus, 
+      if devices havn't work at the same time.*/
+    #if 0
+    dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
+                    client->addr);
+    #else
+    if (status == 0)
+       dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
+                    client->addr);
+    else 
+        dev_set_name(&client->dev, "%d-%02x-%01x", i2c_adapter_id(adap),
+                    client->addr,status);
+    #endif
+    
        status = device_register(&client->dev);
        if (status)
                goto out_err;
@@ -947,6 +966,33 @@ static int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 {
        return device_for_each_child(&adapter->dev, &addr, __i2c_check_addr);
 }
+/* ddl@rock-chips.com : Devices which have some i2c addr can work in same i2c bus, 
+      if devices havn't work at the same time.*/
+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