Skip to contentSkip to conversation

2.4.20-pre2 i2c updates

PATCH New Albert Cranford 1 participant 1 message Aug 13, 2002 I2C

lore
Share & tools
lore
#0 lore raw

PATCH 2/4 2.4.20-pre2 i2c updates

Hello Marcelo,
Please apply the following four tested patches that update 2.4.20-pre2 with these I2C changes:
o Support for SMBus 2.0 PEC Packet Error Checking
o New adapter-i2c-frodo for SA 1110 board
o New adapter-i2c-rpx for embeded MPC8XX
o Remove compat code for < 2.4
o Replace cli()&sti() with spin_{un}lock_irq()
o Updated documentation
Thanks,
Albert

drivers/i2c/i2c-core.c 2002-07-23 08:56:54.000000000 -0400 renamed from drivers/i2c/i2c-core.c.orig 2002-07-23 01:43:58.000000000 -0400 +273 -96
@@ -18,9 +18,10 @@
 /* ------------------------------------------------------------------------- */
 
 /* With some changes from Kyösti Mälkki <[email protected]>.
-   All SMBus-related things are written by Frodo Looijaard <[email protected]> */
+   All SMBus-related things are written by Frodo Looijaard <[email protected]>
+   SMBus 2.0 support by Mark Studebaker <[email protected]>                */
 
-/* $Id: i2c-core.c,v 1.64 2001/08/13 01:35:56 mds Exp $ */
+/* $Id: i2c-core.c,v 1.83 2002/07/08 01:37:15 mds Exp $ */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -28,7 +29,6 @@
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/config.h>
-
 #include <linux/i2c.h>
 
 /* ----- compatibility stuff ----------------------------------------------- */
@@ -36,10 +36,6 @@
 #include <linux/version.h>
 #include <linux/init.h>
 
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
-#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
-#endif
-
 #include <asm/uaccess.h>
 
 /* ----- global defines ---------------------------------------------------- */
@@ -84,10 +80,6 @@
 static int i2cproc_init(void);
 static int i2cproc_cleanup(void);
 
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,27))
-static void monitor_bus_i2c(struct inode *inode, int fill);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */
-
 static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count, 
                                 loff_t *ppos);
 static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
@@ -99,12 +91,6 @@
        read:           i2cproc_bus_read,
 };
 
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,48))
-static struct inode_operations i2cproc_inode_operations = {
-       &i2cproc_operations
-};
-#endif
-
 static int i2cproc_initialized = 0;
 
 #else /* undef CONFIG_PROC_FS */
@@ -158,22 +144,14 @@
 
                proc_entry = create_proc_entry(name,0,proc_bus);
                if (! proc_entry) {
-                       printk("i2c-core.o: Could not create /proc/bus/%s\n",
+                       printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/%s\n",
                               name);
                        res = -ENOENT;
                        goto ERROR1;
                }
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,48))
                proc_entry->proc_fops = &i2cproc_operations;
-#else
-               proc_entry->ops = &i2cproc_inode_operations;
-#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27))
                proc_entry->owner = THIS_MODULE;
-#else
-               proc_entry->fill_inode = &monitor_bus_i2c;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */
                adap->inode = proc_entry->low_ino;
        }
 
@@ -188,7 +166,7 @@
                        drivers[j]->attach_adapter(adap);
        DRV_UNLOCK();
        
-       DEB(printk("i2c-core.o: adapter %s registered as adapter %d.\n",
+       DEB(printk(KERN_DEBUG "i2c-core.o: adapter %s registered as adapter %d.\n",
                   adap->name,i));
 
        return 0;       
@@ -214,7 +192,7 @@
                if (adap == adapters[i])
                        break;
        if (I2C_ADAP_MAX == i) {
-               printk( "i2c-core.o: unregister_adapter adap [%s] not found.\n",
+               printk( KERN_WARNING "i2c-core.o: unregister_adapter adap [%s] not found.\n",
                        adap->name);
                res = -ENODEV;
                goto ERROR0;
@@ -229,7 +207,7 @@
        for (j = 0; j < I2C_DRIVER_MAX; j++) 
                if (drivers[j] && (drivers[j]->flags & I2C_DF_DUMMY))
                        if ((res = drivers[j]->attach_adapter(adap))) {
-                               printk("i2c-core.o: can't detach adapter %s "
+                               printk(KERN_WARNING "i2c-core.o: can't detach adapter %s "
                                       "while detaching driver %s: driver not "
                                       "detached!",adap->name,drivers[j]->name);
                                goto ERROR1;    
@@ -247,7 +225,7 @@
                     * must be deleted, as this would cause invalid states.
                     */
                        if ((res=client->driver->detach_client(client))) {
-                               printk("i2c-core.o: adapter %s not "
+                               printk(KERN_ERR "i2c-core.o: adapter %s not "
                                        "unregistered, because client at "
                                        "address %02x can't be detached. ",
                                        adap->name, client->addr);
@@ -266,7 +244,7 @@
        adap_count--;
        
        ADAP_UNLOCK();  
-       DEB(printk("i2c-core.o: adapter unregistered: %s\n",adap->name));
+       DEB(printk(KERN_DEBUG "i2c-core.o: adapter unregistered: %s\n",adap->name));
        return 0;
 
 ERROR0:
@@ -305,7 +283,7 @@
        
        DRV_UNLOCK();   /* driver was successfully added */
        
-       DEB(printk("i2c-core.o: driver %s registered.\n",driver->name));
+       DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name));
        
        ADAP_LOCK();
 
@@ -340,7 +318,7 @@
         * attached. If so, detach them to be able to kill the driver 
         * afterwards.
         */
-       DEB2(printk("i2c-core.o: unregister_driver - looking for clients.\n"));
+       DEB2(printk(KERN_DEBUG "i2c-core.o: 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.
@@ -350,7 +328,7 @@
                struct i2c_adapter *adap = adapters[k];
                if (adap == NULL) /* skip empty entries. */
                        continue;
-               DEB2(printk("i2c-core.o: examining adapter %s:\n",
+               DEB2(printk(KERN_DEBUG "i2c-core.o: examining adapter %s:\n",
                            adap->name));
                if (driver->flags & I2C_DF_DUMMY) {
                /* DUMMY drivers do not register their clients, so we have to
@@ -359,7 +337,7 @@
                 * this or hell will break loose...  
                 */
                        if ((res = driver->attach_adapter(adap))) {
-                               printk("i2c-core.o: while unregistering "
+                               printk(KERN_WARNING "i2c-core.o: while unregistering "
                                       "dummy driver %s, adapter %s could "
                                       "not be detached properly; driver "
                                       "not unloaded!",driver->name,
@@ -372,19 +350,17 @@
                                struct i2c_client *client = adap->clients[j];
                                if (client != NULL && 
                                    client->driver == driver) {
-                                       DEB2(printk("i2c-core.o: "
+                                       DEB2(printk(KERN_DEBUG "i2c-core.o: "
                                                    "detaching client %s:\n",
                                                    client->name));
                                        if ((res = driver->
                                                        detach_client(client)))
                                        {
-                                               printk("i2c-core.o: while "
+                                               printk(KERN_ERR "i2c-core.o: while "
                                                       "unregistering driver "
                                                       "`%s', the client at "
-                                                      "address %02x of "
-                                                      "adapter `%s' could not"
-                                                      "be detached; driver"
-                                                      "not unloaded!",
+                                                      "address %02x of adapter `%s' could not be "
+                                                      "detached; driver not unloaded!",
                                                       driver->name,
                                                       client->addr,
                                                       adap->name);
@@ -400,7 +376,7 @@
        driver_count--;
        DRV_UNLOCK();
        
-       DEB(printk("i2c-core.o: driver unregistered: %s\n",driver->name));
+       DEB(printk(KERN_DEBUG "i2c-core.o: driver unregistered: %s\n",driver->name));
        return 0;
 }
 
@@ -436,10 +412,10 @@
        
        if (adapter->client_register) 
                if (adapter->client_register(client)) 
-                       printk("i2c-core.o: warning: client_register seems "
+                       printk(KERN_DEBUG "i2c-core.o: warning: client_register seems "
                               "to have failed for client %02x at adapter %s\n",
                               client->addr,adapter->name);
-       DEB(printk("i2c-core.o: client [%s] registered to adapter [%s](pos. %d).\n",
+       DEB(printk(KERN_DEBUG "i2c-core.o: client [%s] registered to adapter [%s](pos. %d).\n",
                client->name, adapter->name,i));
 
        if(client->flags & I2C_CLIENT_ALLOW_USE)
@@ -470,7 +446,7 @@
        
        if (adapter->client_unregister != NULL) 
                if ((res = adapter->client_unregister(client))) {
-                       printk("i2c-core.o: client_unregister [%s] failed, "
+                       printk(KERN_ERR "i2c-core.o: client_unregister [%s] failed, "
                               "client not detached",client->name);
                        return res;
                }
@@ -478,7 +454,7 @@
        adapter->clients[i] = NULL;
        adapter->client_count--;
 
-       DEB(printk("i2c-core.o: client [%s] unregistered.\n",client->name));
+       DEB(printk(KERN_DEBUG "i2c-core.o: client [%s] unregistered.\n",client->name));
        return 0;
 }
 
@@ -611,18 +587,6 @@
 
 #ifdef CONFIG_PROC_FS
 
-#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,27))
-/* Monitor access to /proc/bus/i2c*; make unloading i2c-proc impossible
-   if some process still uses it or some file in it */
-void monitor_bus_i2c(struct inode *inode, int fill)
-{
-       if (fill)
-               MOD_INC_USE_COUNT;
-       else
-               MOD_DEC_USE_COUNT;
-}
-#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,37)) */
-
 /* This function generates the output for /proc/bus/i2c */
 int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof, 
                  void *private)
@@ -659,12 +623,12 @@
        int i,j,k,order_nr,len=0,len_total;
        int order[I2C_CLIENT_MAX];
 
-       if (count > 4000)
+       if (count > 4096)
                return -EINVAL; 
        len_total = file->f_pos + count;
        /* Too bad if this gets longer (unlikely) */
-       if (len_total > 4000)
-               len_total = 4000;
+       if (len_total > 4096)
+               len_total = 4096;
        for (i = 0; i < I2C_ADAP_MAX; i++)
                if (adapters[i]->inode == inode->i_ino) {
                /* We need a bit of slack in the kernel buffer; this makes the
@@ -720,22 +684,18 @@
        i2cproc_initialized = 0;
 
        if (! proc_bus) {
-               printk("i2c-core.o: /proc/bus/ does not exist");
+               printk(KERN_ERR "i2c-core.o: /proc/bus/ does not exist");
                i2cproc_cleanup();
                return -ENOENT;
        } 
        proc_bus_i2c = create_proc_entry("i2c",0,proc_bus);
        if (!proc_bus_i2c) {
-               printk("i2c-core.o: Could not create /proc/bus/i2c");
+               printk(KERN_ERR "i2c-core.o: Could not create /proc/bus/i2c");
                i2cproc_cleanup();
                return -ENOENT;
        }
        proc_bus_i2c->read_proc = &read_bus_i2c;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27))
        proc_bus_i2c->owner = THIS_MODULE;
-#else
-       proc_bus_i2c->fill_inode = &monitor_bus_i2c;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27)) */
        i2cproc_initialized += 2;
        return 0;
 }
@@ -763,7 +723,7 @@
        int ret;
 
        if (adap->algo->master_xfer) {
-               DEB2(printk("i2c-core.o: master_xfer: %s with %d msgs.\n",
+               DEB2(printk(KERN_DEBUG "i2c-core.o: master_xfer: %s with %d msgs.\n",
                            adap->name,num));
 
                I2C_LOCK(adap);
@@ -772,7 +732,7 @@
 
                return ret;
        } else {
-               printk("i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
+               printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
                       adap->id);
                return -ENOSYS;
        }
@@ -790,7 +750,7 @@
                msg.len = count;
                (const char *)msg.buf = buf;
        
-               DEB2(printk("i2c-core.o: master_send: writing %d bytes on %s.\n",
+               DEB2(printk(KERN_DEBUG "i2c-core.o: master_send: writing %d bytes on %s.\n",
                        count,client->adapter->name));
        
                I2C_LOCK(adap);
@@ -802,7 +762,7 @@
                 */
                return (ret == 1 )? count : ret;
        } else {
-               printk("i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
+               printk(KERN_ERR "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
                       client->adapter->id);
                return -ENOSYS;
        }
@@ -820,14 +780,14 @@
                msg.len = count;
                msg.buf = buf;
 
-               DEB2(printk("i2c-core.o: master_recv: reading %d bytes on %s.\n",
+               DEB2(printk(KERN_DEBUG "i2c-core.o: master_recv: reading %d bytes on %s.\n",
                        count,client->adapter->name));
        
                I2C_LOCK(adap);
                ret = adap->algo->master_xfer(adap,&msg,1);
                I2C_UNLOCK(adap);
        
-               DEB2(printk("i2c-core.o: master_recv: return:%d (count:%d, addr:0x%02x)\n",
+               DEB2(printk(KERN_DEBUG "i2c-core.o: 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
@@ -835,7 +795,7 @@
                */
                return (ret == 1 )? count : ret;
        } else {
-               printk("i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
+               printk(KERN_DEBUG "i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
                       client->adapter->id);
                return -ENOSYS;
        }
@@ -848,7 +808,7 @@
        int ret = 0;
        struct i2c_adapter *adap = client->adapter;
 
-       DEB2(printk("i2c-core.o: i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg));
+       DEB2(printk(KERN_DEBUG "i2c-core.o: i2c ioctl, cmd: 0x%x, arg: %#lx\n", cmd, arg));
        switch ( cmd ) {
                case I2C_RETRIES:
                        adap->retries = arg;
@@ -893,7 +853,7 @@
                        if (((adap_id == address_data->force[i]) || 
                             (address_data->force[i] == ANY_I2C_BUS)) &&
                             (addr == address_data->force[i+1])) {
-                               DEB2(printk("i2c-core.o: found force parameter for adapter %d, addr %04x\n",
+                               DEB2(printk(KERN_DEBUG "i2c-core.o: found force parameter for adapter %d, addr %04x\n",
                                            adap_id,addr));
                                if ((err = found_proc(adapter,addr,0,0)))
                                        return err;
@@ -911,7 +871,7 @@
                        if (((adap_id == address_data->ignore[i]) || 
                            ((address_data->ignore[i] == ANY_I2C_BUS))) &&
                            (addr == address_data->ignore[i+1])) {
-                               DEB2(printk("i2c-core.o: found ignore parameter for adapter %d, "
+                               DEB2(printk(KERN_DEBUG "i2c-core.o: found ignore parameter for adapter %d, "
                                     "addr %04x\n", adap_id ,addr));
                                found = 1;
                        }
@@ -923,7 +883,7 @@
                            ((address_data->ignore_range[i]==ANY_I2C_BUS))) &&
                            (addr >= address_data->ignore_range[i+1]) &&
                            (addr <= address_data->ignore_range[i+2])) {
-                               DEB2(printk("i2c-core.o: found ignore_range parameter for adapter %d, "
+                               DEB2(printk(KERN_DEBUG "i2c-core.o: found ignore_range parameter for adapter %d, "
                                            "addr %04x\n", adap_id,addr));
                                found = 1;
                        }
@@ -938,7 +898,7 @@
                     i += 1) {
                        if (addr == address_data->normal_i2c[i]) {
                                found = 1;
-                               DEB2(printk("i2c-core.o: found normal i2c entry for adapter %d, "
+                               DEB2(printk(KERN_DEBUG "i2c-core.o: found normal i2c entry for adapter %d, "
                                            "addr %02x", adap_id,addr));
                        }
                }
@@ -949,7 +909,7 @@
                        if ((addr >= address_data->normal_i2c_range[i]) &&
                            (addr <= address_data->normal_i2c_range[i+1])) {
                                found = 1;
-                               DEB2(printk("i2c-core.o: found normal i2c_range entry for adapter %d, "
+                               DEB2(printk(KERN_DEBUG "i2c-core.o: found normal i2c_range entry for adapter %d, "
                                            "addr %04x\n", adap_id,addr));
                        }
                }
@@ -961,7 +921,7 @@
                            ((address_data->probe[i] == ANY_I2C_BUS))) &&
                            (addr == address_data->probe[i+1])) {
                                found = 1;
-                               DEB2(printk("i2c-core.o: found probe parameter for adapter %d, "
+                               DEB2(printk(KERN_DEBUG "i2c-core.o: found probe parameter for adapter %d, "
                                            "addr %04x\n", adap_id,addr));
                        }
                }
@@ -973,7 +933,7 @@
                           (addr >= address_data->probe_range[i+1]) &&
                           (addr <= address_data->probe_range[i+2])) {
                                found = 1;
-                               DEB2(printk("i2c-core.o: found probe_range parameter for adapter %d, "
+                               DEB2(printk(KERN_DEBUG "i2c-core.o: found probe_range parameter for adapter %d, "
                                            "addr %04x\n", adap_id,addr));
                        }
                }
@@ -1003,6 +963,123 @@
 
 /* The SMBus parts */
 
+#define POLY    (0x1070U << 3) 
+static u8
+crc8(u16 data)
+{
+       int i;
+  
+       for(i = 0; i < 8; i++) {
+               if (data & 0x8000) 
+                       data = data ^ POLY;
+               data = data << 1;
+       }
+       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. */
+u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+{
+       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);
+       return crc;
+}
+
+u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+{
+       return i2c_smbus_partial_pec(0, count, first, 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)
+{
+       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;    
+}
+
+int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
+                        union i2c_smbus_data *data)
+{
+       u8 buf[3], rpec, cpec;
+
+       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) {
+               DEB(printk(KERN_DEBUG "i2c-core.o: Bad PEC 0x%02x vs. 0x%02x\n",
+                          rpec, cpec));
+               return -1;
+       }
+       return 0;       
+}
+
 extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
 {
        return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -1021,8 +1098,9 @@
 
 extern 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,NULL);
+                             I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,&data);
 }
 
 extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
@@ -1100,8 +1178,8 @@
 {
        union i2c_smbus_data data;
        int i;
-       if (length > 32)
-               length = 32;
+       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;
@@ -1110,13 +1188,50 @@
                              I2C_SMBUS_BLOCK_DATA,&data);
 }
 
+/* Returns the number of read bytes */
+extern 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];
+}
+
+/* Returns the number of read bytes */
+extern 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];
+       }
+}
+
 extern 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 > 32)
-               length = 32;
+       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;
@@ -1178,30 +1293,54 @@
                break;
        case I2C_SMBUS_PROC_CALL:
                num = 2; /* Special case */
+               read_write = I2C_SMBUS_READ;
                msg[0].len = 3;
                msg[1].len = 2;
                msgbuf0[1] = data->word & 0xff;
                msgbuf0[2] = (data->word >> 8) & 0xff;
                break;
        case I2C_SMBUS_BLOCK_DATA:
+       case I2C_SMBUS_BLOCK_DATA_PEC:
                if (read_write == I2C_SMBUS_READ) {
-                       printk("i2c-core.o: Block read not supported under "
-                              "I2C emulation!\n");
-               return -1;
+                       printk(KERN_ERR "i2c-core.o: Block read not supported "
+                              "under I2C emulation!\n");
+                       return -1;
                } else {
                        msg[0].len = data->block[0] + 2;
-                       if (msg[0].len > 34) {
-                               printk("i2c-core.o: smbus_access called with "
+                       if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
+                               printk(KERN_ERR "i2c-core.o: smbus_access called with "
                                       "invalid block write size (%d)\n",
-                                      msg[0].len);
+                                      data->block[0]);
                                return -1;
                        }
+                       if(size == I2C_SMBUS_BLOCK_DATA_PEC)
+                               (msg[0].len)++;
                        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:
+               printk(KERN_ERR "i2c-core.o: 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;
+               } else {
+                       msg[0].len = data->block[0] + 2;
+                       if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 2) {
+                               printk("i2c-core.o: i2c_smbus_xfer_emulated called with "
+                                      "invalid block write size (%d)\n",
+                                      data->block[0]);
+                               return -1;
+                       }
+                       for (i = 0; i < data->block[0]; i++)
+                               msgbuf0[i] = data->block[i+1];
+               }
+               break;
        default:
-               printk("i2c-core.o: smbus_access called with invalid size (%d)\n",
+               printk(KERN_ERR "i2c-core.o: smbus_access called with invalid size (%d)\n",
                       size);
                return -1;
        }
@@ -1221,6 +1360,12 @@
                        case I2C_SMBUS_PROC_CALL:
                                data->word = msgbuf1[0] | (msgbuf1[1] << 8);
                                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[i+1] = msgbuf1[i];
+                               break;
                }
        return 0;
 }
@@ -1231,7 +1376,29 @@
                    union i2c_smbus_data * data)
 {
        s32 res;
-       flags = flags & I2C_M_TEN;
+       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) {
                I2C_LOCK(adapter);
                res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
@@ -1240,6 +1407,14 @@
        } 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;
 }
 
@@ -1263,7 +1438,7 @@
 
 static int __init i2c_init(void)
 {
-       printk("i2c-core.o: i2c core module\n");
+       printk(KERN_INFO "i2c-core.o: i2c core module version %s (%s)\n", I2C_VERSION, I2C_DATE);
        memset(adapters,0,sizeof(adapters));
        memset(drivers,0,sizeof(drivers));
        adap_count=0;
@@ -1401,6 +1576,8 @@
 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);
drivers/i2c/i2c-dev.c 2002-07-23 09:01:28.000000000 -0400 renamed from drivers/i2c/i2c-dev.c.orig 2001-10-11 11:05:47.000000000 -0400 +30 -57

259 lines not on this page · raw message

include/linux/i2c-dev.h 2002-07-23 01:54:44.000000000 -0400 renamed from include/linux/i2c-dev.h.orig 2001-10-11 11:05:47.000000000 -0400 +39 -2

65 lines not on this page · raw message

include/linux/i2c-id.h 2002-07-23 01:45:21.000000000 -0400 renamed from include/linux/i2c-id.h.orig 2001-10-11 11:05:47.000000000 -0400 +29 -2
@@ -20,7 +20,7 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
 /* ------------------------------------------------------------------------- */
 
-/* $Id: i2c-id.h,v 1.35 2001/08/12 17:22:20 mds Exp $ */
+/* $Id: i2c-id.h,v 1.52 2002/07/10 13:28:44 abz Exp $ */
 
 #ifndef I2C_ID_H
 #define I2C_ID_H
@@ -90,6 +90,14 @@
 #define I2C_DRIVERID_DRP3510   43     /* ADR decoder (Astra Radio)     */
 #define I2C_DRIVERID_SP5055    44     /* Satellite tuner               */
 #define I2C_DRIVERID_STV0030   45     /* Multipurpose switch           */
+#define I2C_DRIVERID_SAA7108   46     /* video decoder, image scaler   */
+#define I2C_DRIVERID_DS1307    47     /* DS1307 real time clock        */
+#define I2C_DRIVERID_ADV717x   48     /* ADV 7175/7176 video encoder   */
+#define I2C_DRIVERID_ZR36067   49     /* Zoran 36067 video encoder     */
+#define I2C_DRIVERID_ZR36120   50     /* Zoran 36120 video encoder     */
+#define I2C_DRIVERID_24LC32A   51              /* Microchip 24LC32A 32k EEPROM */
+
+
 
 #define I2C_DRIVERID_EXP0      0xF0    /* experimental use id's        */
 #define I2C_DRIVERID_EXP1      0xF1
@@ -98,6 +106,8 @@
 
 #define I2C_DRIVERID_I2CDEV    900
 #define I2C_DRIVERID_I2CPROC   901
+#define I2C_DRIVERID_ARP        902    /* SMBus ARP Client              */
+#define I2C_DRIVERID_ALERT      903    /* SMBus Alert Responder Client  */
 
 /* IDs --   Use DRIVERIDs 1000-1999 for sensors. 
    These were originally in sensors.h in the lm_sensors package */
@@ -127,6 +137,12 @@
 #define I2C_DRIVERID_ADM1024 1025
 #define I2C_DRIVERID_IT87 1026
 #define I2C_DRIVERID_CH700X 1027 /* single driver for CH7003-7009 digital pc to tv encoders */
+#define I2C_DRIVERID_FSCPOS 1028
+#define I2C_DRIVERID_FSCSCY 1029
+#define I2C_DRIVERID_PCF8591 1030
+#define I2C_DRIVERID_SMSC47M1 1031
+#define I2C_DRIVERID_VT1211 1032
+#define I2C_DRIVERID_LM92 1033
 
 /*
  * ---- Adapter types ----------------------------------------------------
@@ -143,10 +159,12 @@
 #define I2C_ALGO_ISA   0x050000        /* lm_sensors ISA pseudo-adapter */
 #define I2C_ALGO_SAA7146 0x060000      /* SAA 7146 video decoder bus   */
 #define I2C_ALGO_ACB   0x070000        /* ACCESS.bus algorithm         */
-
+#define I2C_ALGO_IIC    0x080000       /* ITE IIC bus */
+#define I2C_ALGO_SAA7134 0x090000
 #define I2C_ALGO_EC     0x100000        /* ACPI embedded controller     */
 
 #define I2C_ALGO_MPC8XX 0x110000       /* MPC8xx PowerPC I2C algorithm */
+#define I2C_ALGO_OCP    0x120000       /* IBM or otherwise On-chip I2C algorithm */
 
 #define I2C_ALGO_EXP   0x800000        /* experimental                 */
 
@@ -174,9 +192,11 @@
 #define I2C_HW_B_I810  0x0a    /* Intel I810                           */
 #define I2C_HW_B_VOO   0x0b    /* 3dfx Voodoo 3 / Banshee              */
 #define I2C_HW_B_PPORT  0x0c   /* Primitive parallel port adapter      */
+#define I2C_HW_B_SAVG  0x0d    /* Savage 4                             */
 #define I2C_HW_B_RIVA  0x10    /* Riva based graphics cards            */
 #define I2C_HW_B_IOC   0x11    /* IOC bit-wiggling                     */
 #define I2C_HW_B_TSUNA  0x12   /* DEC Tsunami chipset                  */
+#define I2C_HW_B_FRODO  0x13    /* 2d3D, Inc. SA-1110 Development Board */
 
 /* --- PCF 8584 based algorithms                                       */
 #define I2C_HW_P_LP    0x00    /* Parallel port interface              */
@@ -189,6 +209,13 @@
 /* --- MPC8xx PowerPC adapters                                         */
 #define I2C_HW_MPC8XX_EPON 0x00        /* Eponymous MPC8xx I2C adapter         */
 
+/* --- ITE based algorithms                                            */
+#define I2C_HW_I_IIC   0x00    /* controller on the ITE */
+
+/* --- PowerPC on-chip adapters                                                */
+#define I2C_HW_OCP 0x00        /* IBM on-chip I2C adapter      */
+
+
 /* --- SMBus only adapters                                             */
 #define I2C_HW_SMBUS_PIIX4     0x00
 #define I2C_HW_SMBUS_ALI15X3   0x01
drivers/i2c/i2c-proc.c 2002-07-23 09:14:57.000000000 -0400 renamed from drivers/i2c/i2c-proc.c.orig 2002-02-25 14:37:57.000000000 -0500 +20 -35

171 lines not on this page · raw message

include/linux/i2c-proc.h 2002-07-23 01:45:21.000000000 -0400 renamed from include/linux/i2c-proc.h.orig 2001-10-11 11:05:47.000000000 -0400 +3 -2
@@ -1,6 +1,7 @@
 /*
-    sensors.h - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
+    i2c-proc.h - Part of the i2c package
+    was originally sensors.h - Part of lm_sensors, Linux kernel modules
+                               for hardware monitoring
     Copyright (c) 1998, 1999  Frodo Looijaard <[email protected]>
 
     This program is free software; you can redistribute it and/or modify
include/linux/i2c.h 2002-08-13 00:21:05.000000000 -0400 renamed from include/linux/i2c.h.orig 2001-10-11 11:05:47.000000000 -0400 +47 -17

149 lines not on this page · raw message

Signature · 2 lines
Albert Cranford Deerfield Beach FL USA
[email protected]