]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/i2c/i2c-core.c
[PATCH] hwmon: hwmon vs i2c, second round (01/11)
[karo-tx-linux.git] / drivers / i2c / i2c-core.c
index a22e53badacbe95efa5e0451be2b8236a8d60cc5..372b5996d045ac1970ff45f7a15cafae04a8d9ad 100644 (file)
@@ -21,7 +21,6 @@
    All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
    SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com>                */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -62,7 +61,7 @@ static int i2c_bus_resume(struct device * dev)
        return rc;
 }
 
-static struct bus_type i2c_bus_type = {
+struct bus_type i2c_bus_type = {
        .name =         "i2c",
        .match =        i2c_device_match,
        .suspend =      i2c_bus_suspend,
@@ -79,13 +78,13 @@ static int i2c_device_remove(struct device *dev)
        return 0;
 }
 
-static void i2c_adapter_dev_release(struct device *dev)
+void i2c_adapter_dev_release(struct device *dev)
 {
        struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
        complete(&adap->dev_released);
 }
 
-static struct device_driver i2c_adapter_driver = {
+struct device_driver i2c_adapter_driver = {
        .name = "i2c_adapter",
        .bus = &i2c_bus_type,
        .probe = i2c_device_probe,
@@ -98,7 +97,7 @@ static void i2c_adapter_class_dev_release(struct class_device *dev)
        complete(&adap->class_dev_released);
 }
 
-static struct class i2c_adapter_class = {
+struct class i2c_adapter_class = {
        .name =         "i2c-adapter",
        .release =      &i2c_adapter_class_dev_release,
 };
@@ -157,7 +156,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
                goto out_unlock;
        }
 
-       res = idr_get_new(&i2c_adapter_idr, NULL, &id);
+       res = idr_get_new(&i2c_adapter_idr, adap, &id);
        if (res < 0) {
                if (res == -EAGAIN)
                        res = -ENOMEM;
@@ -189,6 +188,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
        strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
        class_device_register(&adap->class_dev);
 
+       dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
+
        /* inform drivers of new adapters */
        list_for_each(item,&drivers) {
                driver = list_entry(item, struct i2c_driver, list);
@@ -197,8 +198,6 @@ int i2c_add_adapter(struct i2c_adapter *adap)
                        driver->attach_adapter(adap);
        }
 
-       dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
-
 out_unlock:
        up(&core_lists);
        return res;
@@ -221,8 +220,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
                        break;
        }
        if (adap_from_list != adap) {
-               pr_debug("I2C: Attempting to delete an unregistered "
-                        "adapter\n");
+               pr_debug("i2c-core: attempting to delete unregistered "
+                        "adapter [%s]\n", adap->name);
                res = -EINVAL;
                goto out_unlock;
        }
@@ -231,15 +230,14 @@ int i2c_del_adapter(struct i2c_adapter *adap)
                driver = list_entry(item, struct i2c_driver, list);
                if (driver->detach_adapter)
                        if ((res = driver->detach_adapter(adap))) {
-                               dev_warn(&adap->dev, "can't detach adapter "
-                                        "while detaching driver %s: driver not "
-                                        "detached!", driver->name);
+                               dev_err(&adap->dev, "detach_adapter failed "
+                                       "for driver [%s]\n", driver->name);
                                goto out_unlock;
                        }
        }
 
        /* detach any active clients. This must be done first, because
-        * it can fail; in which case we give upp. */
+        * it can fail; in which case we give up. */
        list_for_each_safe(item, _n, &adap->clients) {
                client = list_entry(item, struct i2c_client, list);
 
@@ -248,9 +246,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
                 * must be deleted, as this would cause invalid states.
                 */
                if ((res=client->driver->detach_client(client))) {
-                       dev_err(&adap->dev, "adapter not "
-                               "unregistered, because client at "
-                               "address %02x can't be detached. ",
+                       dev_err(&adap->dev, "detach_client failed for client "
+                               "[%s] at address 0x%02x\n", client->name,
                                client->addr);
                        goto out_unlock;
                }
@@ -271,7 +268,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        /* free dynamically allocated bus id */
        idr_remove(&i2c_adapter_idr, adap->nr);
 
-       dev_dbg(&adap->dev, "adapter unregistered\n");
+       dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name);
 
  out_unlock:
        up(&core_lists);
@@ -304,7 +301,7 @@ int i2c_add_driver(struct i2c_driver *driver)
                goto out_unlock;
        
        list_add_tail(&driver->list,&drivers);
-       pr_debug("i2c-core: driver %s registered.\n", driver->name);
+       pr_debug("i2c-core: driver [%s] registered\n", driver->name);
 
        /* now look for instances of driver on our adapters */
        if (driver->flags & I2C_DF_NOTIFY) {
@@ -332,21 +329,17 @@ int i2c_del_driver(struct i2c_driver *driver)
        /* Have a look at each adapter, if clients of this driver are still
         * attached. If so, detach them to be able to kill the driver 
         * afterwards.
-        */
-       pr_debug("i2c-core: unregister_driver - looking for clients.\n");
-       /* removing clients does not depend on the notify flag, else 
+        *
+        * Removing clients does not depend on the notify flag, else
         * invalid operation might (will!) result, when using stale client
         * pointers.
         */
        list_for_each(item1,&adapters) {
                adap = list_entry(item1, struct i2c_adapter, list);
-               dev_dbg(&adap->dev, "examining adapter\n");
                if (driver->detach_adapter) {
                        if ((res = driver->detach_adapter(adap))) {
-                               dev_warn(&adap->dev, "while unregistering "
-                                      "dummy driver %s, adapter could "
-                                      "not be detached properly; driver "
-                                      "not unloaded!",driver->name);
+                               dev_err(&adap->dev, "detach_adapter failed "
+                                       "for driver [%s]\n", driver->name);
                                goto out_unlock;
                        }
                } else {
@@ -354,16 +347,13 @@ int i2c_del_driver(struct i2c_driver *driver)
                                client = list_entry(item2, struct i2c_client, list);
                                if (client->driver != driver)
                                        continue;
-                               pr_debug("i2c-core.o: detaching client %s:\n", client->name);
+                               dev_dbg(&adap->dev, "detaching client [%s] "
+                                       "at 0x%02x\n", client->name,
+                                       client->addr);
                                if ((res = driver->detach_client(client))) {
-                                       dev_err(&adap->dev, "while "
-                                               "unregistering driver "
-                                               "`%s', the client at "
-                                               "address %02x of "
-                                               "adapter could not "
-                                               "be detached; driver "
-                                               "not unloaded!",
-                                               driver->name,
+                                       dev_err(&adap->dev, "detach_client "
+                                               "failed for client [%s] at "
+                                               "0x%02x\n", client->name,
                                                client->addr);
                                        goto out_unlock;
                                }
@@ -373,7 +363,7 @@ int i2c_del_driver(struct i2c_driver *driver)
 
        driver_unregister(&driver->driver);
        list_del(&driver->list);
-       pr_debug("i2c-core: driver unregistered: %s\n", driver->name);
+       pr_debug("i2c-core: driver [%s] unregistered\n", driver->name);
 
  out_unlock:
        up(&core_lists);
@@ -418,15 +408,12 @@ int i2c_attach_client(struct i2c_client *client)
        
        if (adapter->client_register)  {
                if (adapter->client_register(client))  {
-                       dev_warn(&adapter->dev, "warning: client_register "
-                               "seems to have failed for client %02x\n",
-                               client->addr);
+                       dev_dbg(&adapter->dev, "client_register "
+                               "failed for client [%s] at 0x%02x\n",
+                               client->name, client->addr);
                }
        }
 
-       dev_dbg(&adapter->dev, "client [%s] registered to adapter\n",
-               client->name);
-
        if (client->flags & I2C_CLIENT_ALLOW_USE)
                client->usage_count = 0;
 
@@ -437,7 +424,8 @@ int i2c_attach_client(struct i2c_client *client)
        
        snprintf(&client->dev.bus_id[0], sizeof(client->dev.bus_id),
                "%d-%04x", i2c_adapter_id(adapter), client->addr);
-       pr_debug("registering %s\n", client->dev.bus_id);
+       dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
+               client->name, client->dev.bus_id);
        device_register(&client->dev);
        device_create_file(&client->dev, &dev_attr_client_name);
        
@@ -450,15 +438,19 @@ int i2c_detach_client(struct i2c_client *client)
        struct i2c_adapter *adapter = client->adapter;
        int res = 0;
        
-       if ((client->flags & I2C_CLIENT_ALLOW_USE) && (client->usage_count > 0))
+       if ((client->flags & I2C_CLIENT_ALLOW_USE)
+        && (client->usage_count > 0)) {
+               dev_warn(&client->dev, "Client [%s] still busy, "
+                        "can't detach\n", client->name);
                return -EBUSY;
+       }
 
        if (adapter->client_unregister)  {
                res = adapter->client_unregister(client);
                if (res) {
                        dev_err(&client->dev,
-                              "client_unregister [%s] failed, "
-                              "client not detached", client->name);
+                               "client_unregister [%s] failed, "
+                               "client not detached\n", client->name);
                        goto out;
                }
        }
@@ -612,27 +604,16 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
 
-       if (client->adapter->algo->master_xfer) {
-               msg.addr   = client->addr;
-               msg.flags = client->flags & I2C_M_TEN;
-               msg.len = count;
-               msg.buf = (char *)buf;
+       msg.addr = client->addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.len = count;
+       msg.buf = (char *)buf;
        
-               dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n",
-                       count);
-       
-               down(&adap->bus_lock);
-               ret = adap->algo->master_xfer(adap,&msg,1);
-               up(&adap->bus_lock);
+       ret = i2c_transfer(adap, &msg, 1);
 
-               /* if everything went ok (i.e. 1 msg transmitted), return #bytes
-                * transmitted, else error code.
-                */
-               return (ret == 1 )? count : ret;
-       } else {
-               dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-               return -ENOSYS;
-       }
+       /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+          transmitted, else error code. */
+       return (ret == 1) ? count : ret;
 }
 
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
@@ -640,31 +621,18 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
        struct i2c_adapter *adap=client->adapter;
        struct i2c_msg msg;
        int ret;
-       if (client->adapter->algo->master_xfer) {
-               msg.addr   = client->addr;
-               msg.flags = client->flags & I2C_M_TEN;
-               msg.flags |= I2C_M_RD;
-               msg.len = count;
-               msg.buf = buf;
-
-               dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n",
-                       count);
-       
-               down(&adap->bus_lock);
-               ret = adap->algo->master_xfer(adap,&msg,1);
-               up(&adap->bus_lock);
-       
-               dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n",
-                       ret, count, client->addr);
-       
-               /* if everything went ok (i.e. 1 msg transmitted), return #bytes
-               * transmitted, else error code.
-               */
-               return (ret == 1 )? count : ret;
-       } else {
-               dev_err(&client->adapter->dev, "I2C level transfers not supported\n");
-               return -ENOSYS;
-       }
+
+       msg.addr = client->addr;
+       msg.flags = client->flags & I2C_M_TEN;
+       msg.flags |= I2C_M_RD;
+       msg.len = count;
+       msg.buf = buf;
+
+       ret = i2c_transfer(adap, &msg, 1);
+
+       /* If everything went ok (i.e. 1 msg transmitted), return #bytes
+          transmitted, else error code. */
+       return (ret == 1) ? count : ret;
 }
 
 
@@ -694,6 +662,28 @@ int i2c_control(struct i2c_client *client,
  * Will not work for 10-bit addresses!
  * ----------------------------------------------------
  */
+/* Return: kind (>= 0) if force found, -1 if not found */
+static inline int i2c_probe_forces(struct i2c_adapter *adapter, int addr,
+                                  unsigned short **forces)
+{
+       unsigned short kind;
+       int j, adap_id = i2c_adapter_id(adapter);
+
+       for (kind = 0; forces[kind]; kind++) {
+               for (j = 0; forces[kind][j] != I2C_CLIENT_END; j += 2) {
+                       if ((forces[kind][j] == adap_id ||
+                            forces[kind][j] == ANY_I2C_BUS)
+                        && forces[kind][j + 1] == addr) {
+                               dev_dbg(&adapter->dev, "found force parameter, "
+                                       "addr 0x%02x, kind %u\n", addr, kind);
+                               return kind;
+                       }
+               }
+       }
+
+       return -1;
+}
+
 int i2c_probe(struct i2c_adapter *adapter,
              struct i2c_client_address_data *address_data,
              int (*found_proc) (struct i2c_adapter *, int, int))
@@ -715,19 +705,15 @@ int i2c_probe(struct i2c_adapter *adapter,
                   at all */
                found = 0;
 
-               for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 2) {
-                       if (((adap_id == address_data->force[i]) || 
-                            (address_data->force[i] == ANY_I2C_BUS)) &&
-                            (addr == address_data->force[i+1])) {
-                               dev_dbg(&adapter->dev, "found force parameter for adapter %d, addr %04x\n",
-                                       adap_id, addr);
-                               if ((err = found_proc(adapter,addr,0)))
+               if (address_data->forces) {
+                       int kind = i2c_probe_forces(adapter, addr,
+                                                   address_data->forces);
+                       if (kind >= 0) { /* force found */
+                               if ((err = found_proc(adapter, addr, kind)))
                                        return err;
-                               found = 1;
+                               continue;
                        }
                }
-               if (found) 
-                       continue;
 
                /* If this address is in one of the ignores, we can forget about
                   it right now */
@@ -742,18 +728,6 @@ int i2c_probe(struct i2c_adapter *adapter,
                                found = 1;
                        }
                }
-               for (i = 0;
-                    !found && (address_data->ignore_range[i] != I2C_CLIENT_END);
-                    i += 3) {
-                       if (((adap_id == address_data->ignore_range[i]) ||
-                           ((address_data->ignore_range[i]==ANY_I2C_BUS))) &&
-                           (addr >= address_data->ignore_range[i+1]) &&
-                           (addr <= address_data->ignore_range[i+2])) {
-                               dev_dbg(&adapter->dev, "found ignore_range parameter for adapter %d, "
-                                       "addr %04x\n", adap_id,addr);
-                               found = 1;
-                       }
-               }
                if (found) 
                        continue;
 
@@ -769,17 +743,6 @@ int i2c_probe(struct i2c_adapter *adapter,
                        }
                }
 
-               for (i = 0;
-                    !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END);
-                    i += 2) {
-                       if ((addr >= address_data->normal_i2c_range[i]) &&
-                           (addr <= address_data->normal_i2c_range[i+1])) {
-                               found = 1;
-                               dev_dbg(&adapter->dev, "found normal i2c_range entry for adapter %d, "
-                                       "addr %04x\n", adap_id,addr);
-                       }
-               }
-
                for (i = 0;
                     !found && (address_data->probe[i] != I2C_CLIENT_END);
                     i += 2) {
@@ -791,18 +754,6 @@ int i2c_probe(struct i2c_adapter *adapter,
                                        "addr %04x\n", adap_id,addr);
                        }
                }
-               for (i = 0;
-                    !found && (address_data->probe_range[i] != I2C_CLIENT_END);
-                    i += 3) {
-                       if (((adap_id == address_data->probe_range[i]) ||
-                          (address_data->probe_range[i] == ANY_I2C_BUS)) &&
-                          (addr >= address_data->probe_range[i+1]) &&
-                          (addr <= address_data->probe_range[i+2])) {
-                               found = 1;
-                               dev_dbg(&adapter->dev, "found probe_range parameter for adapter %d, "
-                                       "addr %04x\n", adap_id,addr);
-                       }
-               }
                if (!found) 
                        continue;
 
@@ -815,30 +766,17 @@ int i2c_probe(struct i2c_adapter *adapter,
        return 0;
 }
 
-/*
- * return id number for a specific adapter
- */
-int i2c_adapter_id(struct i2c_adapter *adap)
-{
-       return adap->nr;
-}
-
 struct i2c_adapter* i2c_get_adapter(int id)
 {
-       struct list_head   *item;
        struct i2c_adapter *adapter;
        
        down(&core_lists);
-       list_for_each(item,&adapters) {
-               adapter = list_entry(item, struct i2c_adapter, list);
-               if (id == adapter->nr &&
-                   try_module_get(adapter->owner)) {
-                       up(&core_lists);
-                       return adapter;
-               }
-       }
+       adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
+       if (adapter && !try_module_get(adapter->owner))
+               adapter = NULL;
+
        up(&core_lists);
-       return NULL;
+       return adapter;
 }
 
 void i2c_put_adapter(struct i2c_adapter *adap)
@@ -1236,6 +1174,12 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
 }
 
 
+/* Next four are needed by i2c-isa */
+EXPORT_SYMBOL_GPL(i2c_adapter_dev_release);
+EXPORT_SYMBOL_GPL(i2c_adapter_driver);
+EXPORT_SYMBOL_GPL(i2c_adapter_class);
+EXPORT_SYMBOL_GPL(i2c_bus_type);
+
 EXPORT_SYMBOL(i2c_add_adapter);
 EXPORT_SYMBOL(i2c_del_adapter);
 EXPORT_SYMBOL(i2c_add_driver);
@@ -1251,7 +1195,6 @@ EXPORT_SYMBOL(i2c_master_send);
 EXPORT_SYMBOL(i2c_master_recv);
 EXPORT_SYMBOL(i2c_control);
 EXPORT_SYMBOL(i2c_transfer);
-EXPORT_SYMBOL(i2c_adapter_id);
 EXPORT_SYMBOL(i2c_get_adapter);
 EXPORT_SYMBOL(i2c_put_adapter);
 EXPORT_SYMBOL(i2c_probe);