vserver 2.0 rc7
[linux-2.6.git] / drivers / i2c / i2c-core.c
index 8663e1b..9011627 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
+#include <linux/idr.h>
 #include <linux/seq_file.h>
 #include <asm/uaccess.h>
 
 static LIST_HEAD(adapters);
 static LIST_HEAD(drivers);
 static DECLARE_MUTEX(core_lists);
+static DEFINE_IDR(i2c_adapter_idr);
 
-int i2c_device_probe(struct device *dev)
+/* match always succeeds, as we want the probe() to tell if we really accept this match */
+static int i2c_device_match(struct device *dev, struct device_driver *drv)
+{
+       return 1;
+}
+
+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);
+       return rc;
+}
+
+static int i2c_bus_resume(struct device * dev)
+{
+       int rc = 0;
+       
+       if (dev->driver && dev->driver->resume)
+               rc = dev->driver->resume(dev,0);
+       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;
 }
 
-int i2c_device_remove(struct device *dev)
+static int i2c_device_remove(struct device *dev)
 {
        return 0;
 }
@@ -113,13 +146,25 @@ static struct device_attribute dev_attr_client_name = {
  */
 int i2c_add_adapter(struct i2c_adapter *adap)
 {
-       static int nr = 0;
+       int id, res = 0;
        struct list_head   *item;
        struct i2c_driver  *driver;
 
        down(&core_lists);
 
-       adap->nr = nr++;
+       if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) {
+               res = -ENOMEM;
+               goto out_unlock;
+       }
+
+       res = idr_get_new(&i2c_adapter_idr, NULL, &id);
+       if (res < 0) {
+               if (res == -EAGAIN)
+                       res = -ENOMEM;
+               goto out_unlock;
+       }
+
+       adap->nr =  id & MAX_ID_MASK;
        init_MUTEX(&adap->bus_lock);
        init_MUTEX(&adap->clist_lock);
        list_add_tail(&adap->list,&adapters);
@@ -151,22 +196,37 @@ int i2c_add_adapter(struct i2c_adapter *adap)
                        /* We ignore the return code; if it fails, too bad */
                        driver->attach_adapter(adap);
        }
-       up(&core_lists);
 
        dev_dbg(&adap->dev, "registered as adapter #%d\n", adap->nr);
-       return 0;
+
+out_unlock:
+       up(&core_lists);
+       return res;
 }
 
 
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
        struct list_head  *item, *_n;
+       struct i2c_adapter *adap_from_list;
        struct i2c_driver *driver;
        struct i2c_client *client;
        int res = 0;
 
        down(&core_lists);
 
+       /* First make sure that this adapter was ever added */
+       list_for_each_entry(adap_from_list, &adapters, list) {
+               if (adap_from_list == adap)
+                       break;
+       }
+       if (adap_from_list != adap) {
+               pr_debug("I2C: Attempting to delete an unregistered "
+                        "adapter\n");
+               res = -EINVAL;
+               goto out_unlock;
+       }
+
        list_for_each(item,&drivers) {
                driver = list_entry(item, struct i2c_driver, list);
                if (driver->detach_adapter)
@@ -208,6 +268,9 @@ int i2c_del_adapter(struct i2c_adapter *adap)
        wait_for_completion(&adap->dev_released);
        wait_for_completion(&adap->class_dev_released);
 
+       /* free dynamically allocated bus id */
+       idr_remove(&i2c_adapter_idr, adap->nr);
+
        dev_dbg(&adap->dev, "adapter unregistered\n");
 
  out_unlock:
@@ -491,18 +554,6 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
        up(&adap->clist_lock);
 }
 
-
-/* match always succeeds, as we want the probe() to tell if we really accept this match */
-static int i2c_device_match(struct device *dev, struct device_driver *drv)
-{
-       return 1;
-}
-
-struct bus_type i2c_bus_type = {
-       .name =         "i2c",
-       .match =        i2c_device_match,
-};
-
 static int __init i2c_init(void)
 {
        int retval;
@@ -531,12 +582,18 @@ module_exit(i2c_exit);
  * ----------------------------------------------------
  */
 
-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
+int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
 {
        int ret;
 
        if (adap->algo->master_xfer) {
-               dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num);
+#ifdef DEBUG
+               for (ret = 0; ret < num; ret++) {
+                       dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, "
+                               "len=%d\n", ret, msgs[ret].flags & I2C_M_RD ?
+                               'R' : 'W', msgs[ret].addr, msgs[ret].len);
+               }
+#endif
 
                down(&adap->bus_lock);
                ret = adap->algo->master_xfer(adap,msgs,num);
@@ -658,7 +715,7 @@ int i2c_probe(struct i2c_adapter *adapter,
                   at all */
                found = 0;
 
-               for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
+               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])) {
@@ -708,7 +765,7 @@ int i2c_probe(struct i2c_adapter *adapter,
                        if (addr == address_data->normal_i2c[i]) {
                                found = 1;
                                dev_dbg(&adapter->dev, "found normal i2c entry for adapter %d, "
-                                       "addr %02x", adap_id,addr);
+                                       "addr %02x\n", adap_id, addr);
                        }
                }
 
@@ -808,7 +865,7 @@ crc8(u16 data)
 /* 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. */
-u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
 {
        int i;
 
@@ -820,7 +877,7 @@ u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
        return crc;
 }
 
-u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
 {
        return i2c_smbus_partial_pec(0, count, first, rest);
 }
@@ -828,8 +885,8 @@ u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
 /* 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. */
-int i2c_smbus_add_pec(u16 addr, u8 command, int size,
-                      union i2c_smbus_data *data)
+static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
+                            union i2c_smbus_data *data)
 {
        u8 buf[3];
 
@@ -858,8 +915,8 @@ int i2c_smbus_add_pec(u16 addr, u8 command, int size,
        return size;    
 }
 
-int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
-                        union i2c_smbus_data *data)
+static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
+                              union i2c_smbus_data *data)
 {
        u8 buf[3], rpec, cpec;
 
@@ -969,35 +1026,8 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
                              I2C_SMBUS_WORD_DATA,&data);
 }
 
-s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
-{
-       union i2c_smbus_data data;
-       data.word = value;
-       if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                          I2C_SMBUS_WRITE,command,
-                          I2C_SMBUS_PROC_CALL, &data))
-               return -1;
-       else
-               return 0x0FFFF & data.word;
-}
-
-/* Returns the number of read bytes */
-s32 i2c_smbus_read_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_BLOCK_DATA,&data))
-               return -1;
-       else {
-               for (i = 1; i <= data.block[0]; i++)
-                       values[i-1] = data.block[i];
-               return data.block[0];
-       }
-}
-
-s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
+s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
+                              u8 length, u8 *values)
 {
        union i2c_smbus_data data;
        int i;
@@ -1007,27 +1037,8 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command, u8 length,
                data.block[i] = values[i-1];
        data.block[0] = length;
        return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                             I2C_SMBUS_WRITE,command,
-                             I2C_SMBUS_BLOCK_DATA,&data);
-}
-
-/* Returns the number of read bytes */
-s32 i2c_smbus_block_process_call(struct i2c_client *client, u8 command, u8 length, u8 *values)
-{
-       union i2c_smbus_data data;
-       int i;
-       if (length > I2C_SMBUS_BLOCK_MAX - 1)
-               return -1;
-       data.block[0] = length;
-       for (i = 1; i <= length; i++)
-               data.block[i] = values[i-1];
-       if(i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                         I2C_SMBUS_WRITE, command,
-                         I2C_SMBUS_BLOCK_PROC_CALL, &data))
-               return -1;
-       for (i = 1; i <= data.block[0]; i++)
-               values[i-1] = data.block[i];
-       return data.block[0];
+                             I2C_SMBUS_WRITE,command,
+                             I2C_SMBUS_BLOCK_DATA,&data);
 }
 
 /* Returns the number of read bytes */
@@ -1046,20 +1057,6 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *val
        }
 }
 
-s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values)
-{
-       union i2c_smbus_data data;
-       int i;
-       if (length > I2C_SMBUS_I2C_BLOCK_MAX)
-               length = I2C_SMBUS_I2C_BLOCK_MAX;
-       for (i = 1; i <= length; i++)
-               data.block[i] = values[i-1];
-       data.block[0] = 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 
    No checking of parameters is done!  */
 static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, 
@@ -1239,22 +1236,6 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
 }
 
 
-/* You should always define `functionality'; the 'else' is just for
-   backward compatibility. */ 
-u32 i2c_get_functionality (struct i2c_adapter *adap)
-{
-       if (adap->algo->functionality)
-               return adap->algo->functionality(adap);
-       else
-               return 0xffffffff;
-}
-
-int i2c_check_functionality (struct i2c_adapter *adap, u32 func)
-{
-       u32 adap_func = i2c_get_functionality (adap);
-       return (func & adap_func) == func;
-}
-
 EXPORT_SYMBOL(i2c_add_adapter);
 EXPORT_SYMBOL(i2c_del_adapter);
 EXPORT_SYMBOL(i2c_add_driver);
@@ -1283,14 +1264,8 @@ EXPORT_SYMBOL(i2c_smbus_read_byte_data);
 EXPORT_SYMBOL(i2c_smbus_write_byte_data);
 EXPORT_SYMBOL(i2c_smbus_read_word_data);
 EXPORT_SYMBOL(i2c_smbus_write_word_data);
-EXPORT_SYMBOL(i2c_smbus_process_call);
-EXPORT_SYMBOL(i2c_smbus_read_block_data);
 EXPORT_SYMBOL(i2c_smbus_write_block_data);
 EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
-EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
-
-EXPORT_SYMBOL(i2c_get_functionality);
-EXPORT_SYMBOL(i2c_check_functionality);
 
 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
 MODULE_DESCRIPTION("I2C-Bus main module");