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 @@
/* ------------------------------------------------------------------------- */
/* 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/kernel.h>
......@@ -371,7 +372,7 @@ int i2c_del_driver(struct i2c_driver *driver)
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->
......@@ -1002,6 +1003,123 @@ int i2c_adapter_id(struct i2c_adapter *adap)
/* 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,
......@@ -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)
{
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)
......@@ -1099,8 +1218,8 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
{
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;
......@@ -1109,6 +1228,26 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
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)
......@@ -1131,8 +1270,8 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
{
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;
......@@ -1194,34 +1333,43 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
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(KERN_ERR "i2c-core.o: Block read not supported under "
"I2C emulation!\n");
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) {
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",
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 = 32;
msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX;
} else {
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 "
"invalid block write size (%d)\n",
data->block[0]);
......@@ -1254,8 +1402,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
/* fixed at 32 for now */
data->block[0] = 32;
for (i = 0; i < 32; i++)
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;
}
......@@ -1268,7 +1416,29 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
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,
......@@ -1277,6 +1447,14 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
} 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;
}
......
......@@ -28,7 +28,7 @@
/* The devfs code is contributed by Philipp Matthias Hahn
<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/kernel.h>
......@@ -236,6 +236,12 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
else
client->flags &= ~I2C_M_TEN;
return 0;
case I2C_PEC:
if (arg)
client->flags |= I2C_CLIENT_PEC;
else
client->flags &= ~I2C_CLIENT_PEC;
return 0;
case I2C_FUNCS:
funcs = i2c_get_functionality(client->adapter);
return (copy_to_user((unsigned long *)arg,&funcs,
......@@ -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_PROC_CALL) &&
(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
printk(KERN_DEBUG "i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
data_arg.size);
......@@ -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) ||
(data_arg.size == I2C_SMBUS_PROC_CALL))
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);
if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_WRITE)) {
if (copy_from_user(&temp, data_arg.data, datasize))
return -EFAULT;
......@@ -367,6 +375,7 @@ int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
data_arg.read_write,
data_arg.command,data_arg.size,&temp);
if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
(data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) ||
(data_arg.read_write == I2C_SMBUS_READ))) {
if (copy_to_user(data_arg.data, &temp, datasize))
return -EFAULT;
......@@ -535,6 +544,8 @@ int i2cdev_cleanup(void)
return 0;
}
EXPORT_NO_SYMBOLS;
#ifdef MODULE
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);
static struct ctl_table_header *i2c_entries[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[] = {
{CTL_DEV, "dev", NULL, 0, 0555},
......@@ -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");
kfree(new_table);
kfree(name);
return -ENOMEM;
return -EPERM;
}
i2c_entries[id - 256] = new_header;
......@@ -188,6 +189,8 @@ int i2c_register_entry(struct i2c_client *client, const char *prefix,
return id;
}
#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;
return 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,
void *buffer, size_t * lenp)
{
......
......@@ -19,7 +19,7 @@
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
#define I2C_DEV_H
......@@ -192,6 +192,27 @@ static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
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
......@@ -20,7 +20,7 @@
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
#define I2C_ID_H
......@@ -91,7 +91,11 @@
#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 */
......@@ -102,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 */
......@@ -134,6 +140,9 @@
#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 ----------------------------------------------------
......@@ -155,6 +164,7 @@
#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 */
......@@ -182,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 */
......@@ -200,6 +212,10 @@
/* --- 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
......
......@@ -23,13 +23,13 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
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
#define I2C_H
#define I2C_DATE "20020322"
#define I2C_VERSION "2.6.3"
#define I2C_DATE "20020719"
#define I2C_VERSION "2.6.4"
#include <linux/i2c-id.h> /* id values of adapters et. al. */
#include <linux/types.h>
......@@ -280,6 +280,9 @@ struct i2c_adapter {
#define I2C_CLIENT_ALLOW_USE 0x01 /* Client allows access */
#define I2C_CLIENT_ALLOW_MULTIPLE_USE 0x02 /* Allow multiple access-locks */
/* 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
* addresses for a driver and for the parameters supplied on the
......@@ -395,6 +398,12 @@ struct i2c_msg {
#define I2C_FUNC_I2C 0x00000001
#define I2C_FUNC_10BIT_ADDR 0x00000002
#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_READ_BYTE 0x00020000
#define I2C_FUNC_SMBUS_WRITE_BYTE 0x00040000
......@@ -409,6 +418,8 @@ struct i2c_msg {
#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_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 | \
I2C_FUNC_SMBUS_WRITE_BYTE
......@@ -422,6 +433,17 @@ struct i2c_msg {
I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
#define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_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 | \
I2C_FUNC_SMBUS_BYTE | \
......@@ -429,16 +451,20 @@ struct i2c_msg {
I2C_FUNC_SMBUS_WORD_DATA | \
I2C_FUNC_SMBUS_PROC_CALL | \
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK | \
I2C_FUNC_SMBUS_I2C_BLOCK_2
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
I2C_FUNC_SMBUS_I2C_BLOCK
/*
* 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 {
__u8 byte;
__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 */
......@@ -454,6 +480,11 @@ union i2c_smbus_data {
#define I2C_SMBUS_PROC_CALL 4
#define I2C_SMBUS_BLOCK_DATA 5
#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:
......@@ -479,6 +510,7 @@ union i2c_smbus_data {
#define I2C_FUNCS 0x0705 /* Get the adapter functionality */
#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/
#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */
#if 0
#define I2C_ACK_TEST 0x0710 /* See if a slave is at a specific address */
#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