Commit 208e1d7a authored by Albert Cranford's avatar Albert Cranford Committed by Linus Torvalds

[PATCH] i2c updates 2/4

Please apply the two of four tested patches that update
2.5.31 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 Replace depreciated cli()&sti() with spin_{un}lock_irq()
 o Updated documentation
parent 76044a7f
...@@ -18,9 +18,10 @@ ...@@ -18,9 +18,10 @@
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi>. /* With some changes from Kysti Mlkki <kmalkki@cc.hut.fi>.
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> */ All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl>
SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> */
/* $Id: i2c-core.c,v 1.73 2002/03/03 17:37:44 mds Exp $ */ /* $Id: i2c-core.c,v 1.83 2002/07/08 01:37:15 mds Exp $ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -371,7 +372,7 @@ int i2c_del_driver(struct i2c_driver *driver) ...@@ -371,7 +372,7 @@ int i2c_del_driver(struct i2c_driver *driver)
struct i2c_client *client = adap->clients[j]; struct i2c_client *client = adap->clients[j];
if (client != NULL && if (client != NULL &&
client->driver == driver) { client->driver == driver) {
DEB2(printk("i2c-core.o: " DEB2(printk(KERN_DEBUG "i2c-core.o: "
"detaching client %s:\n", "detaching client %s:\n",
client->name)); client->name));
if ((res = driver-> if ((res = driver->
...@@ -1002,6 +1003,123 @@ int i2c_adapter_id(struct i2c_adapter *adap) ...@@ -1002,6 +1003,123 @@ int i2c_adapter_id(struct i2c_adapter *adap)
/* The SMBus parts */ /* 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) extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
{ {
return i2c_smbus_xfer(client->adapter,client->addr,client->flags, return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
...@@ -1020,8 +1138,9 @@ extern s32 i2c_smbus_read_byte(struct i2c_client * client) ...@@ -1020,8 +1138,9 @@ extern s32 i2c_smbus_read_byte(struct i2c_client * client)
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value) 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, 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) extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
...@@ -1099,8 +1218,8 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client, ...@@ -1099,8 +1218,8 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
int i; int i;
if (length > 32) if (length > I2C_SMBUS_BLOCK_MAX)
length = 32; length = I2C_SMBUS_BLOCK_MAX;
for (i = 1; i <= length; i++) for (i = 1; i <= length; i++)
data.block[i] = values[i-1]; data.block[i] = values[i-1];
data.block[0] = length; data.block[0] = length;
...@@ -1109,6 +1228,26 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client, ...@@ -1109,6 +1228,26 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
I2C_SMBUS_BLOCK_DATA,&data); 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 */ /* Returns the number of read bytes */
extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
u8 command, u8 *values) u8 command, u8 *values)
...@@ -1131,8 +1270,8 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, ...@@ -1131,8 +1270,8 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
{ {
union i2c_smbus_data data; union i2c_smbus_data data;
int i; int i;
if (length > 32) if (length > I2C_SMBUS_I2C_BLOCK_MAX)
length = 32; length = I2C_SMBUS_I2C_BLOCK_MAX;
for (i = 1; i <= length; i++) for (i = 1; i <= length; i++)
data.block[i] = values[i-1]; data.block[i] = values[i-1];
data.block[0] = length; data.block[0] = length;
...@@ -1194,34 +1333,43 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, ...@@ -1194,34 +1333,43 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
break; break;
case I2C_SMBUS_PROC_CALL: case I2C_SMBUS_PROC_CALL:
num = 2; /* Special case */ num = 2; /* Special case */
read_write = I2C_SMBUS_READ;
msg[0].len = 3; msg[0].len = 3;
msg[1].len = 2; msg[1].len = 2;
msgbuf0[1] = data->word & 0xff; msgbuf0[1] = data->word & 0xff;
msgbuf0[2] = (data->word >> 8) & 0xff; msgbuf0[2] = (data->word >> 8) & 0xff;
break; break;
case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_DATA_PEC:
if (read_write == I2C_SMBUS_READ) { if (read_write == I2C_SMBUS_READ) {
printk(KERN_ERR "i2c-core.o: Block read not supported under " printk(KERN_ERR "i2c-core.o: Block read not supported "
"I2C emulation!\n"); "under I2C emulation!\n");
return -1; return -1;
} else { } else {
msg[0].len = data->block[0] + 2; msg[0].len = data->block[0] + 2;
if (msg[0].len > 34) { if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
printk(KERN_ERR "i2c-core.o: smbus_access called with " printk(KERN_ERR "i2c-core.o: smbus_access called with "
"invalid block write size (%d)\n", "invalid block write size (%d)\n",
data->block[0]); data->block[0]);
return -1; 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]; msgbuf0[i] = data->block[i-1];
} }
break; 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: case I2C_SMBUS_I2C_BLOCK_DATA:
if (read_write == I2C_SMBUS_READ) { if (read_write == I2C_SMBUS_READ) {
msg[1].len = 32; msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
} else { } else {
msg[0].len = data->block[0] + 2; msg[0].len = data->block[0] + 2;
if (msg[0].len > 34) { if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 2) {
printk("i2c-core.o: i2c_smbus_xfer_emulated called with " printk("i2c-core.o: i2c_smbus_xfer_emulated called with "
"invalid block write size (%d)\n", "invalid block write size (%d)\n",
data->block[0]); data->block[0]);
...@@ -1254,8 +1402,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, ...@@ -1254,8 +1402,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
break; break;
case I2C_SMBUS_I2C_BLOCK_DATA: case I2C_SMBUS_I2C_BLOCK_DATA:
/* fixed at 32 for now */ /* fixed at 32 for now */
data->block[0] = 32; data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX;
for (i = 0; i < 32; i++) for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++)
data->block[i+1] = msgbuf1[i]; data->block[i+1] = msgbuf1[i];
break; break;
} }
...@@ -1268,7 +1416,29 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, ...@@ -1268,7 +1416,29 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
union i2c_smbus_data * data) union i2c_smbus_data * data)
{ {
s32 res; 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) { if (adapter->algo->smbus_xfer) {
I2C_LOCK(adapter); I2C_LOCK(adapter);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
...@@ -1277,6 +1447,14 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, ...@@ -1277,6 +1447,14 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
} else } else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
command,size,data); 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; return res;
} }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
/* The devfs code is contributed by Philipp Matthias Hahn /* The devfs code is contributed by Philipp Matthias Hahn
<pmhahn@titan.lahn.de> */ <pmhahn@titan.lahn.de> */
/* $Id: i2c-dev.c,v 1.44 2001/11/19 18:45:02 mds Exp $ */ /* $Id: i2c-dev.c,v 1.46 2002/07/06 02:07:39 mds Exp $ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -236,6 +236,12 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, ...@@ -236,6 +236,12 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
else else
client->flags &= ~I2C_M_TEN; client->flags &= ~I2C_M_TEN;
return 0; return 0;
case I2C_PEC:
if (arg)
client->flags |= I2C_CLIENT_PEC;
else
client->flags &= ~I2C_CLIENT_PEC;
return 0;
case I2C_FUNCS: case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter); funcs = i2c_get_functionality(client->adapter);
return (copy_to_user((unsigned long *)arg,&funcs, return (copy_to_user((unsigned long *)arg,&funcs,
...@@ -312,7 +318,8 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, ...@@ -312,7 +318,8 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
(data_arg.size != I2C_SMBUS_WORD_DATA) && (data_arg.size != I2C_SMBUS_WORD_DATA) &&
(data_arg.size != I2C_SMBUS_PROC_CALL) && (data_arg.size != I2C_SMBUS_PROC_CALL) &&
(data_arg.size != I2C_SMBUS_BLOCK_DATA) && (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA)) { (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) &&
(data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) {
#ifdef DEBUG #ifdef DEBUG
printk(KERN_DEBUG "i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n", printk(KERN_DEBUG "i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.size); data_arg.size);
...@@ -355,10 +362,11 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, ...@@ -355,10 +362,11 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
(data_arg.size == I2C_SMBUS_PROC_CALL)) (data_arg.size == I2C_SMBUS_PROC_CALL))
datasize = sizeof(data_arg.data->word); datasize = sizeof(data_arg.data->word);
else /* size == I2C_SMBUS_BLOCK_DATA */ else /* size == smbus block, i2c block, or block proc. call */
datasize = sizeof(data_arg.data->block); datasize = sizeof(data_arg.data->block);
if ((data_arg.size == I2C_SMBUS_PROC_CALL) || if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_WRITE)) { (data_arg.read_write == I2C_SMBUS_WRITE)) {
if (copy_from_user(&temp, data_arg.data, datasize)) if (copy_from_user(&temp, data_arg.data, datasize))
return -EFAULT; return -EFAULT;
...@@ -367,6 +375,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, ...@@ -367,6 +375,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
data_arg.read_write, data_arg.read_write,
data_arg.command,data_arg.size,&temp); data_arg.command,data_arg.size,&temp);
if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_READ))) { (data_arg.read_write == I2C_SMBUS_READ))) {
if (copy_to_user(data_arg.data, &temp, datasize)) if (copy_to_user(data_arg.data, &temp, datasize))
return -EFAULT; return -EFAULT;
...@@ -535,6 +544,8 @@ int i2cdev_cleanup(void) ...@@ -535,6 +544,8 @@ int i2cdev_cleanup(void)
return 0; return 0;
} }
EXPORT_NO_SYMBOLS;
#ifdef MODULE #ifdef MODULE
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>"); MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and Simon G. Vogl <simon@tk.uni-linz.ac.at>");
......
...@@ -60,6 +60,7 @@ int __init sensors_init(void); ...@@ -60,6 +60,7 @@ int __init sensors_init(void);
static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX]; static struct ctl_table_header *i2c_entries[SENSORS_ENTRY_MAX];
static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX]; static struct i2c_client *i2c_clients[SENSORS_ENTRY_MAX];
static unsigned short i2c_inodes[SENSORS_ENTRY_MAX];
static ctl_table sysctl_table[] = { static ctl_table sysctl_table[] = {
{CTL_DEV, "dev", NULL, 0, 0555}, {CTL_DEV, "dev", NULL, 0, 0555},
...@@ -172,7 +173,7 @@ int i2c_register_entry(struct i2c_client *client, const char *prefix, ...@@ -172,7 +173,7 @@ int i2c_register_entry(struct i2c_client *client, const char *prefix,
printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n"); printk(KERN_ERR "i2c-proc.o: error: sysctl interface not supported by kernel!\n");
kfree(new_table); kfree(new_table);
kfree(name); kfree(name);
return -ENOMEM; return -EPERM;
} }
i2c_entries[id - 256] = new_header; i2c_entries[id - 256] = new_header;
...@@ -188,6 +189,8 @@ int i2c_register_entry(struct i2c_client *client, const char *prefix, ...@@ -188,6 +189,8 @@ int i2c_register_entry(struct i2c_client *client, const char *prefix,
return id; return id;
} }
#endif /* DEBUG */ #endif /* DEBUG */
i2c_inodes[id - 256] =
new_header->ctl_table->child->child->de->low_ino;
new_header->ctl_table->child->child->de->owner = controlling_mod; new_header->ctl_table->child->child->de->owner = controlling_mod;
return id; return id;
...@@ -210,6 +213,49 @@ void i2c_deregister_entry(int id) ...@@ -210,6 +213,49 @@ void i2c_deregister_entry(int id)
} }
} }
/* Monitor access for /proc/sys/dev/sensors; make unloading i2c-proc.o
impossible if some process still uses it or some file in it */
void i2c_fill_inode(struct inode *inode, int fill)
{
if (fill)
MOD_INC_USE_COUNT;
else
MOD_DEC_USE_COUNT;
}
/* Monitor access for /proc/sys/dev/sensors/ directories; make unloading
the corresponding module impossible if some process still uses it or
some file in it */
void i2c_dir_fill_inode(struct inode *inode, int fill)
{
int i;
struct i2c_client *client;
#ifdef DEBUG
if (!inode) {
printk(KERN_ERR "i2c-proc.o: Warning: inode NULL in fill_inode()\n");
return;
}
#endif /* def DEBUG */
for (i = 0; i < SENSORS_ENTRY_MAX; i++)
if (i2c_clients[i]
&& (i2c_inodes[i] == inode->i_ino)) break;
#ifdef DEBUG
if (i == SENSORS_ENTRY_MAX) {
printk
(KERN_ERR "i2c-proc.o: Warning: inode (%ld) not found in fill_inode()\n",
inode->i_ino);
return;
}
#endif /* def DEBUG */
client = i2c_clients[i];
if (fill)
client->driver->inc_use(client);
else
client->driver->dec_use(client);
}
int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp, int i2c_proc_chips(ctl_table * ctl, int write, struct file *filp,
void *buffer, size_t * lenp) void *buffer, size_t * lenp)
{ {
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: i2c-dev.h,v 1.10 2001/11/19 19:01:46 mds Exp $ */ /* $Id: i2c-dev.h,v 1.11 2002/07/07 15:42:47 mds Exp $ */
#ifndef I2C_DEV_H #ifndef I2C_DEV_H
#define I2C_DEV_H #define I2C_DEV_H
...@@ -192,6 +192,27 @@ static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, ...@@ -192,6 +192,27 @@ static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
I2C_SMBUS_I2C_BLOCK_DATA, &data); I2C_SMBUS_I2C_BLOCK_DATA, &data);
} }
/* Returns the number of read bytes */
static inline __s32 i2c_smbus_block_process_call(int file, __u8 command,
__u8 length, __u8 *values)
{
union i2c_smbus_data data;
int i;
if (length > 32)
length = 32;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length;
if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
I2C_SMBUS_BLOCK_PROC_CALL,&data))
return -1;
else {
for (i = 1; i <= data.block[0]; i++)
values[i-1] = data.block[i];
return data.block[0];
}
}
#endif /* ndef __KERNEL__ */ #endif /* ndef __KERNEL__ */
#endif #endif
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/* $Id: i2c-id.h,v 1.41 2002/03/11 07:18:55 simon Exp $ */ /* $Id: i2c-id.h,v 1.52 2002/07/10 13:28:44 abz Exp $ */
#ifndef I2C_ID_H #ifndef I2C_ID_H
#define I2C_ID_H #define I2C_ID_H
...@@ -91,7 +91,11 @@ ...@@ -91,7 +91,11 @@
#define I2C_DRIVERID_SP5055 44 /* Satellite tuner */ #define I2C_DRIVERID_SP5055 44 /* Satellite tuner */
#define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */ #define I2C_DRIVERID_STV0030 45 /* Multipurpose switch */
#define I2C_DRIVERID_SAA7108 46 /* video decoder, image scaler */ #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 */
...@@ -102,6 +106,8 @@ ...@@ -102,6 +106,8 @@
#define I2C_DRIVERID_I2CDEV 900 #define I2C_DRIVERID_I2CDEV 900
#define I2C_DRIVERID_I2CPROC 901 #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. /* IDs -- Use DRIVERIDs 1000-1999 for sensors.
These were originally in sensors.h in the lm_sensors package */ These were originally in sensors.h in the lm_sensors package */
...@@ -134,6 +140,9 @@ ...@@ -134,6 +140,9 @@
#define I2C_DRIVERID_FSCPOS 1028 #define I2C_DRIVERID_FSCPOS 1028
#define I2C_DRIVERID_FSCSCY 1029 #define I2C_DRIVERID_FSCSCY 1029
#define I2C_DRIVERID_PCF8591 1030 #define I2C_DRIVERID_PCF8591 1030
#define I2C_DRIVERID_SMSC47M1 1031
#define I2C_DRIVERID_VT1211 1032
#define I2C_DRIVERID_LM92 1033
/* /*
* ---- Adapter types ---------------------------------------------------- * ---- Adapter types ----------------------------------------------------
...@@ -155,6 +164,7 @@ ...@@ -155,6 +164,7 @@
#define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */ #define I2C_ALGO_EC 0x100000 /* ACPI embedded controller */
#define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */ #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 */ #define I2C_ALGO_EXP 0x800000 /* experimental */
...@@ -182,9 +192,11 @@ ...@@ -182,9 +192,11 @@
#define I2C_HW_B_I810 0x0a /* Intel I810 */ #define I2C_HW_B_I810 0x0a /* Intel I810 */
#define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */ #define I2C_HW_B_VOO 0x0b /* 3dfx Voodoo 3 / Banshee */
#define I2C_HW_B_PPORT 0x0c /* Primitive parallel port adapter */ #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_RIVA 0x10 /* Riva based graphics cards */
#define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */ #define I2C_HW_B_IOC 0x11 /* IOC bit-wiggling */
#define I2C_HW_B_TSUNA 0x12 /* DEC Tsunami chipset */ #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 */ /* --- PCF 8584 based algorithms */
#define I2C_HW_P_LP 0x00 /* Parallel port interface */ #define I2C_HW_P_LP 0x00 /* Parallel port interface */
...@@ -200,6 +212,10 @@ ...@@ -200,6 +212,10 @@
/* --- ITE based algorithms */ /* --- ITE based algorithms */
#define I2C_HW_I_IIC 0x00 /* controller on the ITE */ #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 */ /* --- SMBus only adapters */
#define I2C_HW_SMBUS_PIIX4 0x00 #define I2C_HW_SMBUS_PIIX4 0x00
#define I2C_HW_SMBUS_ALI15X3 0x01 #define I2C_HW_SMBUS_ALI15X3 0x01
......
...@@ -23,13 +23,13 @@ ...@@ -23,13 +23,13 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
Frodo Looijaard <frodol@dds.nl> */ Frodo Looijaard <frodol@dds.nl> */
/* $Id: i2c.h,v 1.50 2002/03/23 00:53:38 phil Exp $ */ /* $Id: i2c.h,v 1.59 2002/07/19 20:53:45 phil Exp $ */
#ifndef I2C_H #ifndef I2C_H
#define I2C_H #define I2C_H
#define I2C_DATE "20020322" #define I2C_DATE "20020719"
#define I2C_VERSION "2.6.3" #define I2C_VERSION "2.6.4"
#include <linux/i2c-id.h> /* id values of adapters et. al. */ #include <linux/i2c-id.h> /* id values of adapters et. al. */
#include <linux/types.h> #include <linux/types.h>
...@@ -280,6 +280,9 @@ struct i2c_adapter { ...@@ -280,6 +280,9 @@ struct i2c_adapter {
#define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */ #define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */
#define I2C_CLIENT_ALLOW_MULTIPLE_USE 0x02 /* Allow multiple access-locks */ #define I2C_CLIENT_ALLOW_MULTIPLE_USE 0x02 /* Allow multiple access-locks */
/* on an i2c_client */ /* on an i2c_client */
#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
#define I2C_CLIENT_TEN 0x10 /* we have a ten bit chip address */
/* Must equal I2C_M_TEN below */
/* i2c_client_address_data is the struct for holding default client /* i2c_client_address_data is the struct for holding default client
* addresses for a driver and for the parameters supplied on the * addresses for a driver and for the parameters supplied on the
...@@ -395,6 +398,12 @@ struct i2c_msg { ...@@ -395,6 +398,12 @@ struct i2c_msg {
#define I2C_FUNC_I2C 0x00000001 #define I2C_FUNC_I2C 0x00000001
#define I2C_FUNC_10BIT_ADDR 0x00000002 #define I2C_FUNC_10BIT_ADDR 0x00000002
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART} */ #define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /* I2C_M_{REV_DIR_ADDR,NOSTART} */
#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_READ_WORD_DATA_PEC 0x00000800 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC 0x00001000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_PROC_CALL_PEC 0x00002000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL_PEC 0x00004000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_QUICK 0x00010000 #define I2C_FUNC_SMBUS_QUICK 0x00010000
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000 #define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000 #define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
...@@ -409,6 +418,8 @@ struct i2c_msg { ...@@ -409,6 +418,8 @@ struct i2c_msg {
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */ #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK 0x08000000 /* w/ 1-byte reg. addr. */
#define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */ #define I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 0x10000000 /* I2C-like block xfer */
#define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */ #define I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 0x20000000 /* w/ 2-byte reg. addr. */
#define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC 0x40000000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \ #define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \
I2C_FUNC_SMBUS_WRITE_BYTE I2C_FUNC_SMBUS_WRITE_BYTE
...@@ -422,6 +433,17 @@ struct i2c_msg { ...@@ -422,6 +433,17 @@ struct i2c_msg {
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
#define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \ #define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2 I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2
#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC
#define I2C_FUNC_SMBUS_WORD_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \
I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC
#define I2C_FUNC_SMBUS_READ_BYTE_PEC I2C_FUNC_SMBUS_READ_BYTE_DATA
#define I2C_FUNC_SMBUS_WRITE_BYTE_PEC I2C_FUNC_SMBUS_WRITE_BYTE_DATA
#define I2C_FUNC_SMBUS_READ_BYTE_DATA_PEC I2C_FUNC_SMBUS_READ_WORD_DATA
#define I2C_FUNC_SMBUS_WRITE_BYTE_DATA_PEC I2C_FUNC_SMBUS_WRITE_WORD_DATA
#define I2C_FUNC_SMBUS_BYTE_PEC I2C_FUNC_SMBUS_BYTE_DATA
#define I2C_FUNC_SMBUS_BYTE_DATA_PEC I2C_FUNC_SMBUS_WORD_DATA
#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \ #define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \
I2C_FUNC_SMBUS_BYTE | \ I2C_FUNC_SMBUS_BYTE | \
...@@ -429,16 +451,20 @@ struct i2c_msg { ...@@ -429,16 +451,20 @@ struct i2c_msg {
I2C_FUNC_SMBUS_WORD_DATA | \ I2C_FUNC_SMBUS_WORD_DATA | \
I2C_FUNC_SMBUS_PROC_CALL | \ I2C_FUNC_SMBUS_PROC_CALL | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK | \ I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_I2C_BLOCK
/* /*
* Data for SMBus Messages * Data for SMBus Messages
*/ */
#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
#define I2C_SMBUS_I2C_BLOCK_MAX 32 /* Not specified but we use same structure */
union i2c_smbus_data { union i2c_smbus_data {
__u8 byte; __u8 byte;
__u16 word; __u16 word;
__u8 block[33]; /* block[0] is used for length */ __u8 block[I2C_SMBUS_BLOCK_MAX + 3]; /* block[0] is used for length */
/* one more for read length in block process call */
/* and one more for PEC */
}; };
/* smbus_access read or write markers */ /* smbus_access read or write markers */
...@@ -454,6 +480,11 @@ union i2c_smbus_data { ...@@ -454,6 +480,11 @@ union i2c_smbus_data {
#define I2C_SMBUS_PROC_CALL 4 #define I2C_SMBUS_PROC_CALL 4
#define I2C_SMBUS_BLOCK_DATA 5 #define I2C_SMBUS_BLOCK_DATA 5
#define I2C_SMBUS_I2C_BLOCK_DATA 6 #define I2C_SMBUS_I2C_BLOCK_DATA 6
#define I2C_SMBUS_BLOCK_PROC_CALL 7 /* SMBus 2.0 */
#define I2C_SMBUS_BLOCK_DATA_PEC 8 /* SMBus 2.0 */
#define I2C_SMBUS_PROC_CALL_PEC 9 /* SMBus 2.0 */
#define I2C_SMBUS_BLOCK_PROC_CALL_PEC 10 /* SMBus 2.0 */
#define I2C_SMBUS_WORD_DATA_PEC 11 /* SMBus 2.0 */
/* ----- commands for the ioctl like i2c_command call: /* ----- commands for the ioctl like i2c_command call:
...@@ -479,6 +510,7 @@ union i2c_smbus_data { ...@@ -479,6 +510,7 @@ union i2c_smbus_data {
#define I2C_FUNCS 0x0705 /* Get the adapter functionality */ #define I2C_FUNCS 0x0705 /* Get the adapter functionality */
#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/ #define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/
#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */
#if 0 #if 0
#define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */ #define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment