2.4.20-pre2 i2c updates
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]