Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / i2c / i2c-core.c
index 9011627..45e2cdf 100644 (file)
@@ -19,9 +19,9 @@
 
 /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
    All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
-   SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com>                */
+   SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and
+   Jean Delvare <khali@linux-fr.org> */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/idr.h>
 #include <linux/seq_file.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 
 
 static LIST_HEAD(adapters);
 static LIST_HEAD(drivers);
-static DECLARE_MUTEX(core_lists);
+static DEFINE_MUTEX(core_lists);
 static DEFINE_IDR(i2c_adapter_idr);
 
 /* match always succeeds, as we want the probe() to tell if we really accept this match */
@@ -49,7 +51,7 @@ static int i2c_bus_suspend(struct device * dev, pm_message_t state)
        int rc = 0;
 
        if (dev->driver && dev->driver->suspend)
-               rc = dev->driver->suspend(dev,state,0);
+               rc = dev->driver->suspend(dev, state);
        return rc;
 }
 
@@ -58,17 +60,10 @@ static int i2c_bus_resume(struct device * dev)
        int rc = 0;
        
        if (dev->driver && dev->driver->resume)
-               rc = dev->driver->resume(dev,0);
+               rc = dev->driver->resume(dev);
        return rc;
 }
 
-static struct bus_type i2c_bus_type = {
-       .name =         "i2c",
-       .match =        i2c_device_match,
-       .suspend =      i2c_bus_suspend,
-       .resume =       i2c_bus_resume,
-};
-
 static int i2c_device_probe(struct device *dev)
 {
        return -ENODEV;
@@ -79,17 +74,25 @@ static int i2c_device_remove(struct device *dev)
        return 0;
 }
 
-static void i2c_adapter_dev_release(struct device *dev)
+struct bus_type i2c_bus_type = {
+       .name =         "i2c",
+       .match =        i2c_device_match,
+       .probe =        i2c_device_probe,
+       .remove =       i2c_device_remove,
+       .suspend =      i2c_bus_suspend,
+       .resume =       i2c_bus_resume,
+};
+
+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 = {
+       .owner = THIS_MODULE,
        .name = "i2c_adapter",
        .bus = &i2c_bus_type,
-       .probe = i2c_device_probe,
-       .remove = i2c_device_remove,
 };
 
 static void i2c_adapter_class_dev_release(struct class_device *dev)
@@ -98,12 +101,13 @@ 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 = {
+       .owner =        THIS_MODULE,
        .name =         "i2c-adapter",
        .release =      &i2c_adapter_class_dev_release,
 };
 
-static ssize_t show_adapter_name(struct device *dev, char *buf)
+static ssize_t show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
        return sprintf(buf, "%s\n", adap->name);
@@ -117,7 +121,7 @@ static void i2c_client_release(struct device *dev)
        complete(&client->released);
 }
 
-static ssize_t show_client_name(struct device *dev, char *buf)
+static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct i2c_client *client = to_i2c_client(dev);
        return sprintf(buf, "%s\n", client->name);
@@ -150,14 +154,14 @@ int i2c_add_adapter(struct i2c_adapter *adap)
        struct list_head   *item;
        struct i2c_driver  *driver;
 
-       down(&core_lists);
+       mutex_lock(&core_lists);
 
        if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
                res = -ENOMEM;
                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;
@@ -165,8 +169,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
        }
 
        adap->nr =  id & MAX_ID_MASK;
-       init_MUTEX(&adap->bus_lock);
-       init_MUTEX(&adap->clist_lock);
+       mutex_init(&adap->bus_lock);
+       mutex_init(&adap->clist_lock);
        list_add_tail(&adap->list,&adapters);
        INIT_LIST_HEAD(&adap->clients);
 
@@ -189,18 +193,18 @@ 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);
-               if (driver->flags & I2C_DF_NOTIFY)
+               if (driver->attach_adapter)
                        /* We ignore the return code; if it fails, too bad */
                        driver->attach_adapter(adap);
        }
 
-       dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
-
 out_unlock:
-       up(&core_lists);
+       mutex_unlock(&core_lists);
        return res;
 }
 
@@ -213,7 +217,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        struct i2c_client *client;
        int res = 0;
 
-       down(&core_lists);
+       mutex_lock(&core_lists);
 
        /* First make sure that this adapter was ever added */
        list_for_each_entry(adap_from_list, &adapters, list) {
@@ -221,8 +225,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,26 +235,21 @@ 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->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);
 
-               /* detaching devices is unconditional of the set notify
-                * flag, as _all_ clients that reside on the adapter
-                * 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,10 +270,10 @@ 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);
+       mutex_unlock(&core_lists);
        return res;
 }
 
@@ -285,39 +284,37 @@ int i2c_del_adapter(struct i2c_adapter *adap)
  * chips.
  */
 
-int i2c_add_driver(struct i2c_driver *driver)
+int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 {
        struct list_head   *item;
        struct i2c_adapter *adapter;
-       int res = 0;
-
-       down(&core_lists);
+       int res;
 
        /* add the driver to the list of i2c drivers in the driver core */
-       driver->driver.name = driver->name;
+       driver->driver.owner = owner;
        driver->driver.bus = &i2c_bus_type;
-       driver->driver.probe = i2c_device_probe;
-       driver->driver.remove = i2c_device_remove;
 
        res = driver_register(&driver->driver);
        if (res)
-               goto out_unlock;
+               return res;
        
+       mutex_lock(&core_lists);
+
        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->driver.name);
 
        /* now look for instances of driver on our adapters */
-       if (driver->flags & I2C_DF_NOTIFY) {
+       if (driver->attach_adapter) {
                list_for_each(item,&adapters) {
                        adapter = list_entry(item, struct i2c_adapter, list);
                        driver->attach_adapter(adapter);
                }
        }
 
- out_unlock:
-       up(&core_lists);
-       return res;
+       mutex_unlock(&core_lists);
+       return 0;
 }
+EXPORT_SYMBOL(i2c_register_driver);
 
 int i2c_del_driver(struct i2c_driver *driver)
 {
@@ -327,26 +324,19 @@ int i2c_del_driver(struct i2c_driver *driver)
        
        int res = 0;
 
-       down(&core_lists);
+       mutex_lock(&core_lists);
 
        /* 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 
-        * 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->driver.name);
                                goto out_unlock;
                        }
                } else {
@@ -354,16 +344,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,10 +360,10 @@ 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->driver.name);
 
  out_unlock:
-       up(&core_lists);
+       mutex_unlock(&core_lists);
        return 0;
 }
 
@@ -397,9 +384,9 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 {
        int rval;
 
-       down(&adapter->clist_lock);
+       mutex_lock(&adapter->clist_lock);
        rval = __i2c_check_addr(adapter, addr);
-       up(&adapter->clist_lock);
+       mutex_unlock(&adapter->clist_lock);
 
        return rval;
 }
@@ -408,27 +395,23 @@ int i2c_attach_client(struct i2c_client *client)
 {
        struct i2c_adapter *adapter = client->adapter;
 
-       down(&adapter->clist_lock);
+       mutex_lock(&adapter->clist_lock);
        if (__i2c_check_addr(client->adapter, client->addr)) {
-               up(&adapter->clist_lock);
+               mutex_unlock(&adapter->clist_lock);
                return -EBUSY;
        }
        list_add_tail(&client->list,&adapter->clients);
-       up(&adapter->clist_lock);
+       mutex_unlock(&adapter->clist_lock);
        
        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;
+       client->usage_count = 0;
 
        client->dev.parent = &client->adapter->dev;
        client->dev.driver = &client->driver->driver;
@@ -437,7 +420,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,25 +434,28 @@ 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->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;
                }
        }
 
-       down(&adapter->clist_lock);
+       mutex_lock(&adapter->clist_lock);
        list_del(&client->list);
        init_completion(&client->released);
        device_remove_file(&client->dev, &dev_attr_client_name);
        device_unregister(&client->dev);
-       up(&adapter->clist_lock);
+       mutex_unlock(&adapter->clist_lock);
        wait_for_completion(&client->released);
 
  out:
@@ -478,10 +465,10 @@ int i2c_detach_client(struct i2c_client *client)
 static int i2c_inc_use_client(struct i2c_client *client)
 {
 
-       if (!try_module_get(client->driver->owner))
+       if (!try_module_get(client->driver->driver.owner))
                return -ENODEV;
        if (!try_module_get(client->adapter->owner)) {
-               module_put(client->driver->owner);
+               module_put(client->driver->driver.owner);
                return -ENODEV;
        }
 
@@ -490,7 +477,7 @@ static int i2c_inc_use_client(struct i2c_client *client)
 
 static void i2c_dec_use_client(struct i2c_client *client)
 {
-       module_put(client->driver->owner);
+       module_put(client->driver->driver.owner);
        module_put(client->adapter->owner);
 }
 
@@ -502,33 +489,20 @@ int i2c_use_client(struct i2c_client *client)
        if (ret)
                return ret;
 
-       if (client->flags & I2C_CLIENT_ALLOW_USE) {
-               if (client->flags & I2C_CLIENT_ALLOW_MULTIPLE_USE)
-                       client->usage_count++;
-               else if (client->usage_count > 0) 
-                       goto busy;
-               else 
-                       client->usage_count++;
-       }
+       client->usage_count++;
 
        return 0;
- busy:
-       i2c_dec_use_client(client);
-       return -EBUSY;
 }
 
 int i2c_release_client(struct i2c_client *client)
 {
-       if(client->flags & I2C_CLIENT_ALLOW_USE) {
-               if(client->usage_count>0)
-                       client->usage_count--;
-               else {
-                       pr_debug("i2c-core: %s used one too many times\n",
-                               __FUNCTION__);
-                       return -EPERM;
-               }
+       if (!client->usage_count) {
+               pr_debug("i2c-core: %s used one too many times\n",
+                        __FUNCTION__);
+               return -EPERM;
        }
        
+       client->usage_count--;
        i2c_dec_use_client(client);
        
        return 0;
@@ -539,19 +513,19 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
        struct list_head  *item;
        struct i2c_client *client;
 
-       down(&adap->clist_lock);
+       mutex_lock(&adap->clist_lock);
        list_for_each(item,&adap->clients) {
                client = list_entry(item, struct i2c_client, list);
-               if (!try_module_get(client->driver->owner))
+               if (!try_module_get(client->driver->driver.owner))
                        continue;
                if (NULL != client->driver->command) {
-                       up(&adap->clist_lock);
+                       mutex_unlock(&adap->clist_lock);
                        client->driver->command(client,cmd,arg);
-                       down(&adap->clist_lock);
+                       mutex_lock(&adap->clist_lock);
                }
-               module_put(client->driver->owner);
+               module_put(client->driver->driver.owner);
        }
-       up(&adap->clist_lock);
+       mutex_unlock(&adap->clist_lock);
 }
 
 static int __init i2c_init(void)
@@ -595,9 +569,9 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
                }
 #endif
 
-               down(&adap->bus_lock);
+               mutex_lock(&adap->bus_lock);
                ret = adap->algo->master_xfer(adap,msgs,num);
-               up(&adap->bus_lock);
+               mutex_unlock(&adap->bus_lock);
 
                return ret;
        } else {
@@ -612,27 +586,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);
-
-               /* 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;
-       }
+       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;
 }
 
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
@@ -640,31 +603,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,151 +644,148 @@ int i2c_control(struct i2c_client *client,
  * Will not work for 10-bit addresses!
  * ----------------------------------------------------
  */
+static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
+                            int (*found_proc) (struct i2c_adapter *, int, int))
+{
+       int err;
+
+       /* Make sure the address is valid */
+       if (addr < 0x03 || addr > 0x77) {
+               dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
+                        addr);
+               return -EINVAL;
+       }
+
+       /* Skip if already in use */
+       if (i2c_check_addr(adapter, addr))
+               return 0;
+
+       /* Make sure there is something at this address, unless forced */
+       if (kind < 0) {
+               if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+                                  I2C_SMBUS_QUICK, NULL) < 0)
+                       return 0;
+
+               /* prevent 24RF08 corruption */
+               if ((addr & ~0x0f) == 0x50)
+                       i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+                                      I2C_SMBUS_QUICK, NULL);
+       }
+
+       /* Finally call the custom detection function */
+       err = found_proc(adapter, addr, kind);
+
+       /* -ENODEV can be returned if there is a chip at the given address
+          but it isn't supported by this chip driver. We catch it here as
+          this isn't an error. */
+       return (err == -ENODEV) ? 0 : err;
+}
+
 int i2c_probe(struct i2c_adapter *adapter,
              struct i2c_client_address_data *address_data,
              int (*found_proc) (struct i2c_adapter *, int, int))
 {
-       int addr,i,found,err;
+       int i, err;
        int adap_id = i2c_adapter_id(adapter);
 
-       /* Forget it if we can't probe using SMBUS_QUICK */
-       if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
-               return -1;
-
-       for (addr = 0x00; addr <= 0x7f; addr++) {
-
-               /* Skip if already in use */
-               if (i2c_check_addr(adapter,addr))
-                       continue;
-
-               /* If it is in one of the force entries, we don't do any detection
-                  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)))
-                                       return err;
-                               found = 1;
+       /* Force entries are done first, and are not affected by ignore
+          entries */
+       if (address_data->forces) {
+               unsigned short **forces = address_data->forces;
+               int kind;
+
+               for (kind = 0; forces[kind]; kind++) {
+                       for (i = 0; forces[kind][i] != I2C_CLIENT_END;
+                            i += 2) {
+                               if (forces[kind][i] == adap_id
+                                || forces[kind][i] == ANY_I2C_BUS) {
+                                       dev_dbg(&adapter->dev, "found force "
+                                               "parameter for adapter %d, "
+                                               "addr 0x%02x, kind %d\n",
+                                               adap_id, forces[kind][i + 1],
+                                               kind);
+                                       err = i2c_probe_address(adapter,
+                                               forces[kind][i + 1],
+                                               kind, found_proc);
+                                       if (err)
+                                               return err;
+                               }
                        }
                }
-               if (found) 
-                       continue;
+       }
 
-               /* If this address is in one of the ignores, we can forget about
-                  it right now */
-               for (i = 0;
-                    !found && (address_data->ignore[i] != I2C_CLIENT_END);
-                    i += 2) {
-                       if (((adap_id == address_data->ignore[i]) || 
-                           ((address_data->ignore[i] == ANY_I2C_BUS))) &&
-                           (addr == address_data->ignore[i+1])) {
-                               dev_dbg(&adapter->dev, "found ignore parameter for adapter %d, "
-                                       "addr %04x\n", adap_id ,addr);
-                               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;
+       /* Stop here if we can't use SMBUS_QUICK */
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
+               if (address_data->probe[0] == I2C_CLIENT_END
+                && address_data->normal_i2c[0] == I2C_CLIENT_END)
+                       return 0;
 
-               /* Now, we will do a detection, but only if it is in the normal or 
-                  probe entries */  
-               for (i = 0;
-                    !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
-                    i += 1) {
-                       if (addr == address_data->normal_i2c[i]) {
-                               found = 1;
-                               dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, "
-                                       "addr %02x\n", adap_id, addr);
-                       }
-               }
+               dev_warn(&adapter->dev, "SMBus Quick command not supported, "
+                        "can't probe for chips\n");
+               return -1;
+       }
 
-               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);
-                       }
+       /* Probe entries are done second, and are not affected by ignore
+          entries either */
+       for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
+               if (address_data->probe[i] == adap_id
+                || address_data->probe[i] == ANY_I2C_BUS) {
+                       dev_dbg(&adapter->dev, "found probe parameter for "
+                               "adapter %d, addr 0x%02x\n", adap_id,
+                               address_data->probe[i + 1]);
+                       err = i2c_probe_address(adapter,
+                                               address_data->probe[i + 1],
+                                               -1, found_proc);
+                       if (err)
+                               return err;
                }
+       }
 
-               for (i = 0;
-                    !found && (address_data->probe[i] != I2C_CLIENT_END);
-                    i += 2) {
-                       if (((adap_id == address_data->probe[i]) ||
-                           ((address_data->probe[i] == ANY_I2C_BUS))) &&
-                           (addr == address_data->probe[i+1])) {
-                               found = 1;
-                               dev_dbg(&adapter->dev, "found probe parameter for adapter %d, "
-                                       "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);
+       /* Normal entries are done last, unless shadowed by an ignore entry */
+       for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
+               int j, ignore;
+
+               ignore = 0;
+               for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
+                    j += 2) {
+                       if ((address_data->ignore[j] == adap_id ||
+                            address_data->ignore[j] == ANY_I2C_BUS)
+                        && address_data->ignore[j + 1]
+                           == address_data->normal_i2c[i]) {
+                               dev_dbg(&adapter->dev, "found ignore "
+                                       "parameter for adapter %d, "
+                                       "addr 0x%02x\n", adap_id,
+                                       address_data->ignore[j + 1]);
                        }
+                       ignore = 1;
+                       break;
                }
-               if (!found) 
+               if (ignore)
                        continue;
 
-               /* OK, so we really should examine this address. First check
-                  whether there is some client here at all! */
-               if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
-                       if ((err = found_proc(adapter,addr,-1)))
-                               return err;
+               dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
+                       "addr 0x%02x\n", adap_id,
+                       address_data->normal_i2c[i]);
+               err = i2c_probe_address(adapter, address_data->normal_i2c[i],
+                                       -1, found_proc);
+               if (err)
+                       return err;
        }
-       return 0;
-}
 
-/*
- * return id number for a specific adapter
- */
-int i2c_adapter_id(struct i2c_adapter *adap)
-{
-       return adap->nr;
+       return 0;
 }
 
 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;
-               }
-       }
-       up(&core_lists);
-       return NULL;
+       mutex_lock(&core_lists);
+       adapter = (struct i2c_adapter *)idr_find(&i2c_adapter_idr, id);
+       if (adapter && !try_module_get(adapter->owner))
+               adapter = NULL;
+
+       mutex_unlock(&core_lists);
+       return adapter;
 }
 
 void i2c_put_adapter(struct i2c_adapter *adap)
@@ -862,101 +809,44 @@ crc8(u16 data)
        return (u8)(data >> 8);
 }
 
-/* CRC over count bytes in the first array plus the bytes in the rest
-   array if it is non-null. rest[0] is the (length of rest) - 1
-   and is included. */
-static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+/* Incremental CRC8 over count bytes in the array pointed to by p */
+static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count)
 {
        int i;
 
        for(i = 0; i < count; i++)
-               crc = crc8((crc ^ first[i]) << 8);
-       if(rest != NULL)
-               for(i = 0; i <= rest[0]; i++)
-                       crc = crc8((crc ^ rest[i]) << 8);
+               crc = crc8((crc ^ p[i]) << 8);
        return crc;
 }
 
-static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+/* Assume a 7-bit address, which is reasonable for SMBus */
+static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)
 {
-       return i2c_smbus_partial_pec(0, count, first, rest);
+       /* The address will be sent first */
+       u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);
+       pec = i2c_smbus_pec(pec, &addr, 1);
+
+       /* The data buffer follows */
+       return i2c_smbus_pec(pec, msg->buf, msg->len);
 }
 
-/* Returns new "size" (transaction type)
-   Note that we convert byte to byte_data and byte_data to word_data
-   rather than invent new xxx_PEC transactions. */
-static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
-                            union i2c_smbus_data *data)
+/* Used for write only transactions */
+static inline void i2c_smbus_add_pec(struct i2c_msg *msg)
 {
-       u8 buf[3];
-
-       buf[0] = addr << 1;
-       buf[1] = command;
-       switch(size) {
-               case I2C_SMBUS_BYTE:
-                       data->byte = i2c_smbus_pec(2, buf, NULL);
-                       size = I2C_SMBUS_BYTE_DATA;
-                       break;
-               case I2C_SMBUS_BYTE_DATA:
-                       buf[2] = data->byte;
-                       data->word = buf[2] ||
-                                   (i2c_smbus_pec(3, buf, NULL) << 8);
-                       size = I2C_SMBUS_WORD_DATA;
-                       break;
-               case I2C_SMBUS_WORD_DATA:
-                       /* unsupported */
-                       break;
-               case I2C_SMBUS_BLOCK_DATA:
-                       data->block[data->block[0] + 1] =
-                                    i2c_smbus_pec(2, buf, data->block);
-                       size = I2C_SMBUS_BLOCK_DATA_PEC;
-                       break;
-       }
-       return size;    
+       msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg);
+       msg->len++;
 }
 
-static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
-                              union i2c_smbus_data *data)
+/* Return <0 on CRC error
+   If there was a write before this read (most cases) we need to take the
+   partial CRC from the write part into account.
+   Note that this function does modify the message (we need to decrease the
+   message length to hide the CRC byte from the caller). */
+static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
 {
-       u8 buf[3], rpec, cpec;
+       u8 rpec = msg->buf[--msg->len];
+       cpec = i2c_smbus_msg_pec(cpec, msg);
 
-       buf[1] = command;
-       switch(size) {
-               case I2C_SMBUS_BYTE_DATA:
-                       buf[0] = (addr << 1) | 1;
-                       cpec = i2c_smbus_pec(2, buf, NULL);
-                       rpec = data->byte;
-                       break;
-               case I2C_SMBUS_WORD_DATA:
-                       buf[0] = (addr << 1) | 1;
-                       buf[2] = data->word & 0xff;
-                       cpec = i2c_smbus_pec(3, buf, NULL);
-                       rpec = data->word >> 8;
-                       break;
-               case I2C_SMBUS_WORD_DATA_PEC:
-                       /* unsupported */
-                       cpec = rpec = 0;
-                       break;
-               case I2C_SMBUS_PROC_CALL_PEC:
-                       /* unsupported */
-                       cpec = rpec = 0;
-                       break;
-               case I2C_SMBUS_BLOCK_DATA_PEC:
-                       buf[0] = (addr << 1);
-                       buf[2] = (addr << 1) | 1;
-                       cpec = i2c_smbus_pec(3, buf, data->block);
-                       rpec = data->block[data->block[0] + 1];
-                       break;
-               case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
-                       buf[0] = (addr << 1) | 1;
-                       rpec = i2c_smbus_partial_pec(partial, 1,
-                                                    buf, data->block);
-                       cpec = data->block[data->block[0] + 1];
-                       break;
-               default:
-                       cpec = rpec = 0;
-                       break;
-       }
        if (rpec != cpec) {
                pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
                        rpec, cpec);
@@ -983,9 +873,8 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
 
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
 {
-       union i2c_smbus_data data;      /* only for PEC */
        return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                             I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
+                             I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
 }
 
 s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
@@ -1030,12 +919,11 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
                               u8 length, u8 *values)
 {
        union i2c_smbus_data data;
-       int i;
+
        if (length > I2C_SMBUS_BLOCK_MAX)
                length = I2C_SMBUS_BLOCK_MAX;
-       for (i = 1; i <= length; i++)
-               data.block[i] = values[i-1];
        data.block[0] = length;
+       memcpy(&data.block[1], values, length);
        return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
                              I2C_SMBUS_WRITE,command,
                              I2C_SMBUS_BLOCK_DATA,&data);
@@ -1045,16 +933,28 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
 s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values)
 {
        union i2c_smbus_data data;
-       int i;
+
        if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
                              I2C_SMBUS_READ,command,
                              I2C_SMBUS_I2C_BLOCK_DATA,&data))
                return -1;
-       else {
-               for (i = 1; i <= data.block[0]; i++)
-                       values[i-1] = data.block[i];
-               return data.block[0];
-       }
+
+       memcpy(values, &data.block[1], data.block[0]);
+       return data.block[0];
+}
+
+s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
+                                  u8 length, u8 *values)
+{
+       union i2c_smbus_data data;
+
+       if (length > I2C_SMBUS_BLOCK_MAX)
+               length = I2C_SMBUS_BLOCK_MAX;
+       data.block[0] = length;
+       memcpy(data.block + 1, values, length);
+       return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                             I2C_SMBUS_WRITE, command,
+                             I2C_SMBUS_I2C_BLOCK_DATA, &data);
 }
 
 /* Simulate a SMBus command using the i2c protocol 
@@ -1068,13 +968,14 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
          need to use only one message; when reading, we need two. We initialize
          most things with sane defaults, to keep the code below somewhat
          simpler. */
-       unsigned char msgbuf0[34];
-       unsigned char msgbuf1[34];
+       unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
+       unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
        int num = read_write == I2C_SMBUS_READ?2:1;
        struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, 
                                  { addr, flags | I2C_M_RD, 0, msgbuf1 }
                                };
        int i;
+       u8 partial_pec = 0;
 
        msgbuf0[0] = command;
        switch(size) {
@@ -1117,7 +1018,6 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                msgbuf0[2] = (data->word >> 8) & 0xff;
                break;
        case I2C_SMBUS_BLOCK_DATA:
-       case I2C_SMBUS_BLOCK_DATA_PEC:
                if (read_write == I2C_SMBUS_READ) {
                        dev_err(&adapter->dev, "Block read not supported "
                               "under I2C emulation!\n");
@@ -1130,23 +1030,20 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                                       data->block[0]);
                                return -1;
                        }
-                       if(size == I2C_SMBUS_BLOCK_DATA_PEC)
-                               (msg[0].len)++;
-                       for (i = 1; i <= msg[0].len; i++)
+                       for (i = 1; i < msg[0].len; i++)
                                msgbuf0[i] = data->block[i-1];
                }
                break;
        case I2C_SMBUS_BLOCK_PROC_CALL:
-       case I2C_SMBUS_BLOCK_PROC_CALL_PEC:
                dev_dbg(&adapter->dev, "Block process call not supported "
                       "under I2C emulation!\n");
                return -1;
        case I2C_SMBUS_I2C_BLOCK_DATA:
                if (read_write == I2C_SMBUS_READ) {
-                       msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
+                       msg[1].len = I2C_SMBUS_BLOCK_MAX;
                } else {
                        msg[0].len = data->block[0] + 1;
-                       if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) {
+                       if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
                                dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "
                                       "invalid block write size (%d)\n",
                                       data->block[0]);
@@ -1162,9 +1059,30 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                return -1;
        }
 
+       i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
+                                     && size != I2C_SMBUS_I2C_BLOCK_DATA);
+       if (i) {
+               /* Compute PEC if first message is a write */
+               if (!(msg[0].flags & I2C_M_RD)) {
+                       if (num == 1) /* Write only */
+                               i2c_smbus_add_pec(&msg[0]);
+                       else /* Write followed by read */
+                               partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
+               }
+               /* Ask for PEC if last message is a read */
+               if (msg[num-1].flags & I2C_M_RD)
+                       msg[num-1].len++;
+       }
+
        if (i2c_transfer(adapter, msg, num) < 0)
                return -1;
 
+       /* Check PEC if last message is a read */
+       if (i && (msg[num-1].flags & I2C_M_RD)) {
+               if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0)
+                       return -1;
+       }
+
        if (read_write == I2C_SMBUS_READ)
                switch(size) {
                        case I2C_SMBUS_BYTE:
@@ -1179,8 +1097,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                                break;
                        case I2C_SMBUS_I2C_BLOCK_DATA:
                                /* fixed at 32 for now */
-                               data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
-                               for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
+                               data->block[0] = I2C_SMBUS_BLOCK_MAX;
+                               for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
                                        data->block[i+1] = msgbuf1[i];
                                break;
                }
@@ -1193,52 +1111,30 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
                    union i2c_smbus_data * data)
 {
        s32 res;
-       int swpec = 0;
-       u8 partial = 0;
 
        flags &= I2C_M_TEN | I2C_CLIENT_PEC;
-       if((flags & I2C_CLIENT_PEC) &&
-          !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) {
-               swpec = 1;
-               if(read_write == I2C_SMBUS_READ &&
-                  size == I2C_SMBUS_BLOCK_DATA)
-                       size = I2C_SMBUS_BLOCK_DATA_PEC;
-               else if(size == I2C_SMBUS_PROC_CALL)
-                       size = I2C_SMBUS_PROC_CALL_PEC;
-               else if(size == I2C_SMBUS_BLOCK_PROC_CALL) {
-                       i2c_smbus_add_pec(addr, command,
-                                         I2C_SMBUS_BLOCK_DATA, data);
-                       partial = data->block[data->block[0] + 1];
-                       size = I2C_SMBUS_BLOCK_PROC_CALL_PEC;
-               } else if(read_write == I2C_SMBUS_WRITE &&
-                         size != I2C_SMBUS_QUICK &&
-                         size != I2C_SMBUS_I2C_BLOCK_DATA)
-                       size = i2c_smbus_add_pec(addr, command, size, data);
-       }
 
        if (adapter->algo->smbus_xfer) {
-               down(&adapter->bus_lock);
+               mutex_lock(&adapter->bus_lock);
                res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
                                                command,size,data);
-               up(&adapter->bus_lock);
+               mutex_unlock(&adapter->bus_lock);
        } else
                res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
                                              command,size,data);
 
-       if(res >= 0 && swpec &&
-          size != I2C_SMBUS_QUICK && size != I2C_SMBUS_I2C_BLOCK_DATA &&
-          (read_write == I2C_SMBUS_READ || size == I2C_SMBUS_PROC_CALL_PEC ||
-           size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) {
-               if(i2c_smbus_check_pec(addr, command, size, partial, data))
-                       return -1;
-       }
        return res;
 }
 
 
+/* 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);
 EXPORT_SYMBOL(i2c_del_driver);
 EXPORT_SYMBOL(i2c_attach_client);
 EXPORT_SYMBOL(i2c_detach_client);
@@ -1251,7 +1147,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);
@@ -1266,6 +1161,7 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data);
 EXPORT_SYMBOL(i2c_smbus_write_word_data);
 EXPORT_SYMBOL(i2c_smbus_write_block_data);
 EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
+EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
 
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus main module");