Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[powerpc.git] / drivers / i2c / i2c-core.c
index dda472e..82ea1b7 100644 (file)
@@ -19,7 +19,8 @@
 
 /* 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/module.h>
 #include <linux/kernel.h>
@@ -29,6 +30,7 @@
 #include <linux/init.h>
 #include <linux/idr.h>
 #include <linux/seq_file.h>
+#include <linux/platform_device.h>
 #include <asm/uaccess.h>
 
 
@@ -48,7 +50,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;
 }
 
@@ -57,7 +59,7 @@ 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;
 }
 
@@ -85,6 +87,7 @@ void i2c_adapter_dev_release(struct device *dev)
 }
 
 struct device_driver i2c_adapter_driver = {
+       .owner = THIS_MODULE,
        .name = "i2c_adapter",
        .bus = &i2c_bus_type,
        .probe = i2c_device_probe,
@@ -98,6 +101,7 @@ static void i2c_adapter_class_dev_release(struct class_device *dev)
 }
 
 struct class i2c_adapter_class = {
+       .owner =        THIS_MODULE,
        .name =         "i2c-adapter",
        .release =      &i2c_adapter_class_dev_release,
 };
@@ -291,6 +295,7 @@ int i2c_add_driver(struct i2c_driver *driver)
        down(&core_lists);
 
        /* add the driver to the list of i2c drivers in the driver core */
+       driver->driver.owner = driver->owner;
        driver->driver.name = driver->name;
        driver->driver.bus = &i2c_bus_type;
        driver->driver.probe = i2c_device_probe;
@@ -706,10 +711,6 @@ int i2c_probe(struct i2c_adapter *adapter,
        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;
-
        /* Force entries are done first, and are not affected by ignore
           entries */
        if (address_data->forces) {
@@ -736,6 +737,17 @@ int i2c_probe(struct i2c_adapter *adapter,
                }
        }
 
+       /* 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;
+
+               dev_warn(&adapter->dev, "SMBus Quick command not supported, "
+                        "can't probe for chips\n");
+               return -1;
+       }
+
        /* 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) {
@@ -820,101 +832,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);
@@ -941,9 +896,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)
@@ -1026,13 +980,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) {
@@ -1075,7 +1030,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");
@@ -1088,23 +1042,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]);
@@ -1120,9 +1071,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:
@@ -1137,8 +1109,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;
                }
@@ -1151,28 +1123,8 @@ 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);
@@ -1183,13 +1135,6 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
                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;
 }