diff -Naur linux-2.6.11-rc4-mm1/drivers/i2c/busses/i2c-i801.c linux-2.6.11-rc4-mm1-bttv/drivers/i2c/busses/i2c-i801.c --- linux-2.6.11-rc4-mm1/drivers/i2c/busses/i2c-i801.c 2005-02-23 10:19:17.972058968 -0800 +++ linux-2.6.11-rc4-mm1-bttv/drivers/i2c/busses/i2c-i801.c 2005-02-24 10:38:03.216827616 -0800 @@ -40,14 +40,6 @@ /* Note: we assume there can only be one I801, with one SMBus interface */ -/* Another note: This interface is extremely sensitive to timing and - failure handling. If you don't wait at least one jiffie after - starting the transaction before checking things, you will screw it - up. If you don't wait a jiffie after the final check, you will - screw it up. If you screw it up by these manners or by abandoning - an operation in progress, the I2C bus is likely stuck and won't - work any more. Gotta love this hardware. */ - #include #include #include @@ -87,8 +79,7 @@ #define SMBHSTCFG_I2C_EN 4 /* Other settings */ -#define MAX_TIMEOUT_US 100000 -#define RETRY_TIME_US 500 /* Retry minimum is 500us */ +#define MAX_TIMEOUT 100 #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ /* I801 command constants */ @@ -114,35 +105,21 @@ "Forcibly enable the I801 at the given address. " "EXTREMELY DANGEROUS!"); +static int i801_transaction(void); +static int i801_block_transaction(union i2c_smbus_data *data, + char read_write, int command); + static unsigned short i801_smba; static struct pci_dev *I801_dev; static int isich4; -struct i801_i2c_data -{ - int i; - int len; - unsigned char hostc; - int block; - int hwpec; - int xact; - int hststs; - int wait_intr; - int finished; - - /* Used to handle removal race conditions. */ - int in_removal; - int in_use; -}; -struct i801_i2c_data i801_data; - static int i801_setup(struct pci_dev *dev) { int error_return = 0; unsigned char temp; /* Note: we keep on searching until we have found 'function 3' */ - if (PCI_FUNC(dev->devfn) != 3) + if(PCI_FUNC(dev->devfn) != 3) return -ENODEV; I801_dev = dev; @@ -159,7 +136,7 @@ } else { pci_read_config_word(I801_dev, SMBBA, &i801_smba); i801_smba &= 0xfff0; - if (i801_smba == 0) { + if(i801_smba == 0) { dev_err(&dev->dev, "SMB base address uninitialized" "- upgrade BIOS or use force_addr=0xaddr\n"); return -ENODEV; @@ -203,93 +180,12 @@ return error_return; } -static void i801_check_hststs(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) -{ - if (d->hststs & 0x10) { - entry->result = -EIO; - dev_dbg(&I801_dev->dev, - "Error: Failed bus transaction\n"); - } else if (d->hststs & 0x08) { - entry->result = -EIO; - dev_err(&I801_dev->dev, "Bus collision!\n"); - /* Clock stops and slave is stuck in mid-transmission */ - } else if (d->hststs & 0x04) { - entry->result = -EIO; - dev_dbg(&I801_dev->dev, "Error: no response!\n"); - } -} - -static void i801_finish(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) -{ - d->finished = 1; - -#ifdef HAVE_PEC - if (isich4 && d->hwpec) { - if (entry->smbus.size != I2C_SMBUS_QUICK && - entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA) - outb_p(0, SMBAUXCTL); - } -#endif - - if (d->block || (entry->result < 0) || - ((entry->smbus.read_write == I2C_SMBUS_WRITE) - || (d->xact == I801_QUICK))) - return; - - switch (d->xact & 0x7f) { - case I801_BYTE: /* Result put in SMBHSTDAT0 */ - case I801_BYTE_DATA: - entry->smbus.data->byte = inb_p(SMBHSTDAT0); - break; - case I801_WORD_DATA: - entry->smbus.data->word = inb_p(SMBHSTDAT0) - + (inb_p(SMBHSTDAT1) << 8); - break; - } -} - -static void i801_transaction_final_check(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) +static int i801_transaction(void) { - i801_check_hststs(adap, entry, d); + int temp; + int result = 0; + int timeout = 0; - if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) - outb_p(inb(SMBHSTSTS), SMBHSTSTS); - - if ((d->hststs = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(&I801_dev->dev, "Failed reset at end of transaction" - "(%02x)\n", d->hststs); - } - dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); -} - -static void i801_transaction_poll(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) -{ - d->hststs = inb_p(SMBHSTSTS); - if (!(d->hststs & 0x01)) { - i801_transaction_final_check(adap, entry, d); - i801_finish(adap, entry, d); - } else if (entry->time_left <= 0) { - dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); - entry->result = -EIO; - i801_transaction_final_check(adap, entry, d); - } -} - -static void i801_transaction_start(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) -{ dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x," "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), @@ -297,368 +193,331 @@ /* Make sure the SMBus host is ready to start transmitting */ /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - if ((d->hststs = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting... \n", - d->hststs); - outb_p(d->hststs, SMBHSTSTS); - if ((d->hststs = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", d->hststs); - entry->result = -EIO; - return; + temp); + outb_p(temp, SMBHSTSTS); + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { + dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp); + return -1; } else { dev_dbg(&I801_dev->dev, "Successfull!\n"); } } outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); -} -static void i801_block_finish(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) -{ - if (entry->smbus.size == I2C_SMBUS_I2C_BLOCK_DATA) { - /* restore saved configuration register value */ - pci_write_config_byte(I801_dev, SMBHSTCFG, d->hostc); - } - - i801_finish(adap, entry, d); -} + /* We will always wait for a fraction of a second! */ + do { + msleep(1); + temp = inb_p(SMBHSTSTS); + } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); -static void i801_block_poll_wait_intr(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) -{ -#ifdef HAVE_PEC - if (entry->result >= 0 && - isich4 && - entry->smbus.size == I2C_SMBUS_BLOCK_DATA_PEC) - { - /* wait for INTR bit as advised by Intel */ - d->hststs = inb_p(SMBHSTSTS); - if (d->hststs & 0x02) { - outb_p(d->hststs, SMBHSTSTS); - i801_block_finish(adap, entry, d); - } else if (entry->time_left <= 0) { - /* Timed out */ - outb_p(d->hststs, SMBHSTSTS); - entry->result = -EIO; - dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); - } - } else -#endif - i801_block_finish(adap, entry, d); -} + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); + result = -1; + } -static void i801_block_next_byte(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) -{ - int smbcmd; - unsigned char errmask; + if (temp & 0x10) { + result = -1; + dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); + } - if (d->i > d->len) { - d->wait_intr = 1; - entry->time_left = MAX_TIMEOUT_US; - i801_block_poll_wait_intr(adap, entry, d); - return; + if (temp & 0x08) { + result = -1; + dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " + "until next hard reset. (sorry!)\n"); + /* Clock stops and slave is stuck in mid-transmission */ } - if (d->i == d->len && entry->smbus.read_write == I2C_SMBUS_READ) - smbcmd = I801_BLOCK_LAST; - else - smbcmd = I801_BLOCK_DATA; - outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); + if (temp & 0x04) { + result = -1; + dev_dbg(&I801_dev->dev, "Error: no response!\n"); + } - dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", d->i, - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); + if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) + outb_p(inb(SMBHSTSTS), SMBHSTSTS); - /* Make sure the SMBus host is ready to start transmitting */ - d->hststs = inb_p(SMBHSTSTS); - if (d->i == 1) { - /* Erronenous conditions before transaction: - * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - errmask=0x9f; - } else { - /* Erronenous conditions during transaction: - * Failed, Bus_Err, Dev_Err, Intr */ - errmask=0x1e; - } - if (d->hststs & errmask) { - dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " - "Resetting... \n", d->hststs); - outb_p(d->hststs, SMBHSTSTS); - if (((d->hststs = inb_p(SMBHSTSTS)) & errmask) != 0x00) { - dev_err(&I801_dev->dev, - "Reset failed! (%02x)\n", d->hststs); - entry->result = -EIO; - return; - } - if (d->i != 1) { - /* if die in middle of block transaction, fail */ - entry->result = -EIO; - return; - } + if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { + dev_dbg(&I801_dev->dev, "Failed reset at end of transaction" + "(%02x)\n", temp); } - - if (d->i == 1) - outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); + dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); + return result; } -/* Called on timer ticks. This checks the result of the - transaction. */ -static void i801_block_poll(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) +/* All-inclusive block transaction function */ +static int i801_block_transaction(union i2c_smbus_data *data, char read_write, + int command) { - d->hststs = inb_p(SMBHSTSTS); - if (!(d->hststs & 0x80)) { - /* Not ready yet */ - if (entry->time_left <= 0) { - dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); - entry->result = -EIO; + int i, len; + int smbcmd; + int temp; + int result = 0; + int timeout; + unsigned char hostc, errmask; + + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + if (read_write == I2C_SMBUS_WRITE) { + /* set I2C_EN bit in configuration register */ + pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); + pci_write_config_byte(I801_dev, SMBHSTCFG, + hostc | SMBHSTCFG_I2C_EN); + } else { + dev_err(&I801_dev->dev, + "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); + return -1; } - return; } - i801_check_hststs(adap, entry, d); - if (d->i == 1 && entry->smbus.read_write == I2C_SMBUS_READ) { - d->len = inb_p(SMBHSTDAT0); - if (d->len < 1) - d->len = 1; - if (d->len > 32) - d->len = 32; - entry->smbus.data->block[0] = d->len; - } - - /* Retrieve/store value in SMBBLKDAT */ - if (entry->smbus.read_write == I2C_SMBUS_READ) - entry->smbus.data->block[d->i] = inb_p(SMBBLKDAT); - if (entry->smbus.read_write == I2C_SMBUS_WRITE && d->i+1 <= d->len) - outb_p(entry->smbus.data->block[d->i+1], SMBBLKDAT); - if ((d->hststs & 0x9e) != 0x00) - outb_p(d->hststs, SMBHSTSTS); /* signals SMBBLKDAT ready */ - - if ((d->hststs = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { - dev_dbg(&I801_dev->dev, - "Bad status (%02x) at end of transaction\n", - d->hststs); - } - dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", d->i, - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); - - if (entry->result) - return; - - (d->i)++; - i801_block_next_byte(adap, entry, d); -} - -static void i801_block_start(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - struct i801_i2c_data *d) -{ - if (entry->smbus.read_write == I2C_SMBUS_WRITE) { - d->len = entry->smbus.data->block[0]; - if (d->len < 1) - d->len = 1; - if (d->len > 32) - d->len = 32; - outb_p(d->len, SMBHSTDAT0); - outb_p(entry->smbus.data->block[1], SMBBLKDAT); + if (read_write == I2C_SMBUS_WRITE) { + len = data->block[0]; + if (len < 1) + len = 1; + if (len > 32) + len = 32; + outb_p(len, SMBHSTDAT0); + outb_p(data->block[1], SMBBLKDAT); } else { - d->len = 32; /* max for reads */ + len = 32; /* max for reads */ } - if(isich4 && entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA) { + if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) { /* set 32 byte buffer */ } - d->i = 1; - i801_block_next_byte(adap, entry, d); -} - -/* General poll routine. Called periodically by the i2c code. */ -static void i801_poll(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - unsigned int us_since_last_poll) -{ - struct i801_i2c_data *d = entry->data; - - dev_dbg(&I801_dev->dev, "Poll call for %p %p at %ld\n", adap, entry, - jiffies); + for (i = 1; i <= len; i++) { + if (i == len && read_write == I2C_SMBUS_READ) + smbcmd = I801_BLOCK_LAST; + else + smbcmd = I801_BLOCK_DATA; + outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); + + dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, + inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), + inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); + + /* Make sure the SMBus host is ready to start transmitting */ + temp = inb_p(SMBHSTSTS); + if (i == 1) { + /* Erronenous conditions before transaction: + * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ + errmask=0x9f; + } else { + /* Erronenous conditions during transaction: + * Failed, Bus_Err, Dev_Err, Intr */ + errmask=0x1e; + } + if (temp & errmask) { + dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " + "Resetting... \n", temp); + outb_p(temp, SMBHSTSTS); + if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { + dev_err(&I801_dev->dev, + "Reset failed! (%02x)\n", temp); + result = -1; + goto END; + } + if (i != 1) { + /* if die in middle of block transaction, fail */ + result = -1; + goto END; + } + } - if (!d) - /* The entry hasn't been started yet. */ - return; + if (i == 1) + outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); - if (d->finished) { - /* We delay an extra poll to keep the hardware happy. - Otherwise the hardware is not ready when we start - the next operation. */ - i2c_op_done(adap, entry); - d->in_use = 0; - return; - } + /* We will always wait for a fraction of a second! */ + timeout = 0; + do { + temp = inb_p(SMBHSTSTS); + msleep(1); + } + while ((!(temp & 0x80)) + && (timeout++ < MAX_TIMEOUT)); - /* Decrement timeout */ - entry->time_left -= us_since_last_poll; + /* If the SMBus is still busy, we give up */ + if (timeout >= MAX_TIMEOUT) { + result = -1; + dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); + } - /* Wait a jiffie normally. */ - entry->call_again_us = RETRY_TIME_US; + if (temp & 0x10) { + result = -1; + dev_dbg(&I801_dev->dev, + "Error: Failed bus transaction\n"); + } else if (temp & 0x08) { + result = -1; + dev_err(&I801_dev->dev, "Bus collision!\n"); + } else if (temp & 0x04) { + result = -1; + dev_dbg(&I801_dev->dev, "Error: no response!\n"); + } - if (d->block) { - if (d->wait_intr) { - i801_block_poll_wait_intr(adap, entry, d); - } else { - i801_block_poll(adap, entry, d); + if (i == 1 && read_write == I2C_SMBUS_READ) { + len = inb_p(SMBHSTDAT0); + if (len < 1) + len = 1; + if (len > 32) + len = 32; + data->block[0] = len; } - if (entry->result < 0) - /* Error, finish the transaction */ - i801_block_finish(adap, entry, d); - } else { - i801_transaction_poll(adap, entry, d); - if (entry->result < 0) - /* Error, finish the transaction */ - i801_finish(adap, entry, d); - } -} -/* Start a general SMBUS transaction on the i801. Figure out what - kind of transaction it is, set it up, and start it. */ -static void i801_start(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry) -{ - struct i801_i2c_data *d = adap->algo_data; + /* Retrieve/store value in SMBBLKDAT */ + if (read_write == I2C_SMBUS_READ) + data->block[i] = inb_p(SMBBLKDAT); + if (read_write == I2C_SMBUS_WRITE && i+1 <= len) + outb_p(data->block[i+1], SMBBLKDAT); + if ((temp & 0x9e) != 0x00) + outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */ + + if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { + dev_dbg(&I801_dev->dev, + "Bad status (%02x) at end of transaction\n", + temp); + } + dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, + inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), + inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); - d->in_use = 1; - if (d->in_removal) { - d->in_use = 0; - entry->result = -ENODEV; - return; + if (result < 0) + goto END; } - dev_dbg(&I801_dev->dev, "start call for %p %p at %ld\n", adap, entry, - jiffies); +#ifdef HAVE_PEC + if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) { + /* wait for INTR bit as advised by Intel */ + timeout = 0; + do { + temp = inb_p(SMBHSTSTS); + msleep(1); + } while ((!(temp & 0x02)) + && (timeout++ < MAX_TIMEOUT)); - if (entry->smbus.size == I2C_SMBUS_I2C_BLOCK_DATA) { - if (entry->smbus.read_write == I2C_SMBUS_WRITE) { - /* set I2C_EN bit in configuration register */ - pci_read_config_byte(I801_dev, SMBHSTCFG, &d->hostc); - pci_write_config_byte(I801_dev, SMBHSTCFG, - d->hostc | SMBHSTCFG_I2C_EN); - } else { - dev_err(&I801_dev->dev, - "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); - d->in_use = 0; - entry->result = -EINVAL; - return; + if (timeout >= MAX_TIMEOUT) { + dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); } + outb_p(temp, SMBHSTSTS); } +#endif + result = 0; +END: + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + /* restore saved configuration register value */ + pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); + } + return result; +} - d->block = 0; - d->hwpec = 0; - d->xact = 0; - d->wait_intr = 0; - d->finished = 0; +/* Return -1 on error. */ +static s32 i801_access(struct i2c_adapter * adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data * data) +{ + int hwpec = 0; + int block = 0; + int ret, xact = 0; #ifdef HAVE_PEC - if (isich4) - d->hwpec = (entry->smbus.flags & I2C_CLIENT_PEC) != 0; + if(isich4) + hwpec = (flags & I2C_CLIENT_PEC) != 0; #endif - switch (entry->smbus.size) { + switch (size) { case I2C_SMBUS_QUICK: - outb_p(((entry->smbus.addr & 0x7f) << 1) - | (entry->smbus.read_write & 0x01), + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - d->xact = I801_QUICK; + xact = I801_QUICK; break; case I2C_SMBUS_BYTE: - outb_p(((entry->smbus.addr & 0x7f) << 1) - | (entry->smbus.read_write & 0x01), + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - if (entry->smbus.read_write == I2C_SMBUS_WRITE) - outb_p(entry->smbus.command, SMBHSTCMD); - d->xact = I801_BYTE; + if (read_write == I2C_SMBUS_WRITE) + outb_p(command, SMBHSTCMD); + xact = I801_BYTE; break; case I2C_SMBUS_BYTE_DATA: - outb_p(((entry->smbus.addr & 0x7f) << 1) - | (entry->smbus.read_write & 0x01), + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - outb_p(entry->smbus.command, SMBHSTCMD); - if (entry->smbus.read_write == I2C_SMBUS_WRITE) - outb_p(entry->smbus.data->byte, SMBHSTDAT0); - d->xact = I801_BYTE_DATA; + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) + outb_p(data->byte, SMBHSTDAT0); + xact = I801_BYTE_DATA; break; case I2C_SMBUS_WORD_DATA: - outb_p(((entry->smbus.addr & 0x7f) << 1) - | (entry->smbus.read_write & 0x01), + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - outb_p(entry->smbus.command, SMBHSTCMD); - if (entry->smbus.read_write == I2C_SMBUS_WRITE) { - outb_p(entry->smbus.data->word & 0xff, SMBHSTDAT0); - outb_p((entry->smbus.data->word & 0xff00) >> 8, - SMBHSTDAT1); + outb_p(command, SMBHSTCMD); + if (read_write == I2C_SMBUS_WRITE) { + outb_p(data->word & 0xff, SMBHSTDAT0); + outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); } - d->xact = I801_WORD_DATA; + xact = I801_WORD_DATA; break; case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_I2C_BLOCK_DATA: #ifdef HAVE_PEC case I2C_SMBUS_BLOCK_DATA_PEC: - if (d->hwpec && entry->smbus.size == I2C_SMBUS_BLOCK_DATA) - entry->smbus.size = I2C_SMBUS_BLOCK_DATA_PEC; + if(hwpec && size == I2C_SMBUS_BLOCK_DATA) + size = I2C_SMBUS_BLOCK_DATA_PEC; #endif - outb_p(((entry->smbus.addr & 0x7f) << 1) - | (entry->smbus.read_write & 0x01), + outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), SMBHSTADD); - outb_p(entry->smbus.command, SMBHSTCMD); - d->block = 1; + outb_p(command, SMBHSTCMD); + block = 1; break; case I2C_SMBUS_PROC_CALL: default: - dev_err(&I801_dev->dev, "Unsupported transaction %d\n", - entry->smbus.size); - entry->result = -EINVAL; - d->in_use = 0; - return; + dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); + return -1; } #ifdef HAVE_PEC - if (isich4 && d->hwpec) { - if (entry->smbus.size != I2C_SMBUS_QUICK && - entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA) + if(isich4 && hwpec) { + if(size != I2C_SMBUS_QUICK && + size != I2C_SMBUS_I2C_BLOCK_DATA) outb_p(1, SMBAUXCTL); /* enable HW PEC */ } #endif - if (d->block) { - i801_block_start(adap, entry, d); - if (entry->result < 0) - /* Error, finish the transaction */ - i801_block_finish(adap, entry, d); - } else { - outb_p(d->xact | ENABLE_INT9, SMBHSTCNT); - i801_transaction_start(adap, entry, d); - if (entry->result < 0) - /* Error, finish the transaction */ - i801_finish(adap, entry, d); - } - - /* Wait extra long here, we want at least 2 ticks to guarantee - we wait >= 1 tick. */ - entry->call_again_us = (1000000 / HZ) * 2; - entry->time_left = MAX_TIMEOUT_US; - - if (d->finished) { - i2c_op_done(adap, entry); - d->in_use = 0; - } else - entry->data = d; + if(block) + ret = i801_block_transaction(data, read_write, size); + else { + outb_p(xact | ENABLE_INT9, SMBHSTCNT); + ret = i801_transaction(); + } + +#ifdef HAVE_PEC + if(isich4 && hwpec) { + if(size != I2C_SMBUS_QUICK && + size != I2C_SMBUS_I2C_BLOCK_DATA) + outb_p(0, SMBAUXCTL); + } +#endif + + if(block) + return ret; + if(ret) + return -1; + if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) + return 0; + + switch (xact & 0x7f) { + case I801_BYTE: /* Result put in SMBHSTDAT0 */ + case I801_BYTE_DATA: + data->byte = inb_p(SMBHSTDAT0); + break; + case I801_WORD_DATA: + data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); + break; + } + return 0; } @@ -678,8 +537,7 @@ static struct i2c_algorithm smbus_algorithm = { .name = "Non-I2C SMBus adapter", .id = I2C_ALGO_SMBUS, - .smbus_start = i801_start, - .poll = i801_poll, + .smbus_xfer = i801_access, .functionality = i801_func, }; @@ -687,7 +545,6 @@ .owner = THIS_MODULE, .class = I2C_CLASS_HWMON, .algo = &smbus_algorithm, - .algo_data = &i801_data, .name = "unset", }; @@ -706,8 +563,7 @@ MODULE_DEVICE_TABLE (pci, i801_ids); -static int __devinit i801_probe(struct pci_dev *dev, - const struct pci_device_id *id) +static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (i801_setup(dev)) { @@ -726,14 +582,6 @@ static void __devexit i801_remove(struct pci_dev *dev) { - struct i801_i2c_data *d = i801_adapter.algo_data; - - /* Shut down any new requests and wait for any in-progress - operations to complete. */ - d->in_removal = 1; - while (d->in_use) - mdelay(1); - i2c_del_adapter(&i801_adapter); release_region(i801_smba, (isich4 ? 16 : 8)); } diff -Naur linux-2.6.11-rc4-mm1/drivers/i2c/i2c-core.c linux-2.6.11-rc4-mm1-bttv/drivers/i2c/i2c-core.c --- linux-2.6.11-rc4-mm1/drivers/i2c/i2c-core.c 2005-02-23 10:19:18.233019296 -0800 +++ linux-2.6.11-rc4-mm1-bttv/drivers/i2c/i2c-core.c 2005-02-24 10:37:01.399225320 -0800 @@ -30,14 +30,8 @@ #include #include #include -#include #include -static int i2c_stop_timer(struct i2c_adapter * adap); -static void i2c_start_timer(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry); - -#define USEC_PER_JIFFIE (1000000 / HZ) static LIST_HEAD(adapters); static LIST_HEAD(drivers); @@ -171,26 +165,11 @@ } adap->nr = id & MAX_ID_MASK; - spin_lock_init(&adap->q_lock); - INIT_LIST_HEAD(&adap->q); init_MUTEX(&adap->bus_lock); init_MUTEX(&adap->clist_lock); list_add_tail(&adap->list,&adapters); INIT_LIST_HEAD(&adap->clients); - adap->timer = kmalloc(sizeof(*adap->timer), GFP_KERNEL); - if (!adap->timer) { - res = -ENOMEM; - goto out_unlock; - } - - init_timer(&adap->timer->timer); - spin_lock_init(&adap->timer->lock); - adap->timer->deleted = 0; - adap->timer->running = 0; - adap->timer->next_call_time = 0; - adap->timer->adapter = adap; - /* Add the adapter to the driver core. * If the parent pointer is not set up, * we add this adapter to the host bus. @@ -233,7 +212,6 @@ struct i2c_driver *driver; struct i2c_client *client; int res = 0; - unsigned long flags; down(&core_lists); @@ -286,17 +264,6 @@ device_unregister(&adap->dev); list_del(&adap->list); - /* Stop the timer and free its memory */ - spin_lock_irqsave(&adap->timer->lock, flags); - if (i2c_stop_timer(adap)) { - spin_unlock_irqrestore(&adap->timer->lock, flags); - kfree(adap->timer); - } else { - adap->timer->deleted = 1; - spin_unlock_irqrestore(&adap->timer->lock, flags); - } - adap->timer = NULL; - /* wait for sysfs to drop all references */ wait_for_completion(&adap->dev_released); wait_for_completion(&adap->class_dev_released); @@ -615,287 +582,15 @@ * ---------------------------------------------------- */ -#define entry_completed(e) (atomic_read(&(e)->completed) <= 0) - -/* Must be called with the q_lock held. */ -static void i2c_start_entry(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) -{ - entry->started = 1; - switch (entry->xfer_type) { - case I2C_OP_I2C: - adap->algo->master_start(adap, entry); - break; - case I2C_OP_SMBUS: - adap->algo->smbus_start(adap, entry); - break; - default: - entry->result = -EINVAL; - i2c_op_done(adap, entry); - } - - if (!entry_completed(entry) && entry->use_timer) - i2c_start_timer(adap, entry); -} - -/* Get the first entry off the head of the queue and lock it there. - The entry is guaranteed to remain first in the list and the handler - not be called until i2c_entry_put() is called. */ -static struct i2c_op_q_entry *_i2c_entry_get(struct i2c_adapter * adap) -{ - struct i2c_op_q_entry * entry = NULL; - - if (!list_empty(&adap->q)) { - struct list_head * link = adap->q.next; - entry = list_entry(link, struct i2c_op_q_entry, link); - if (entry_completed(entry)) - entry = NULL; - else { - int val = atomic_add_return(1, &entry->usecount); - - /* This is subtle. If we increment the - usecount and the value is 1, that means it - was zero before. This means the put() - routine has decremented the value to zero - and is between tha decrement and the - spinlock. In this case, return NULL - because the current list head is complete - and the next list item is not yet - started. */ - if (val == 1) { - atomic_dec(&entry->usecount); - entry = NULL; - } - } - } - pr_debug("_i2c_entry_get %p %p\n", adap, entry); - return entry; -} - -struct i2c_op_q_entry *i2c_entry_get(struct i2c_adapter * adap) -{ - unsigned long flags; - struct i2c_op_q_entry * entry; - - spin_lock_irqsave(&adap->q_lock, flags); - entry = _i2c_entry_get(adap); - spin_unlock_irqrestore(&adap->q_lock, flags); - return entry; -} - -void i2c_entry_put(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) -{ - unsigned long flags; - struct i2c_op_q_entry * new_entry = NULL; - - restart: - pr_debug("i2c_put %p %p\n", adap, entry); - /* Subtle reasons why we don't need a lock before the dec, see - the get routine for more details. */ - if (atomic_dec_and_test(&entry->usecount)) { - spin_lock_irqsave(&adap->q_lock, flags); - list_del(&entry->link); - - /* Get the next entry to start. */ - new_entry = _i2c_entry_get(adap); - spin_unlock_irqrestore(&adap->q_lock, flags); - - entry->handler(entry); - - if (new_entry) { - i2c_start_entry(adap, new_entry); - if (new_entry->start) - complete(new_entry->start); - /* Do tail recursion ourself. */ - entry = new_entry; - goto restart; - } - } -} - -static void i2c_handle_timer(unsigned long data); - -static void i2c_start_timer(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) -{ - unsigned int wait_jiffies; - struct i2c_timer *t = adap->timer; - unsigned long flags; - - wait_jiffies = ((entry->call_again_us + USEC_PER_JIFFIE - 1) - / USEC_PER_JIFFIE); - if (wait_jiffies == 0) - wait_jiffies = 1; - /* This won't be polled from the user code, so - start a timer to poll it. */ - spin_lock_irqsave(&t->lock, flags); - if (! t->running) { - t->timer.expires = jiffies + wait_jiffies; - t->timer.data = (unsigned long) t; - t->timer.function = i2c_handle_timer; - t->running = 1; - t->next_call_time = wait_jiffies * USEC_PER_JIFFIE; - add_timer(&t->timer); - t->sequence = adap->timer_sequence; - } - spin_unlock_irqrestore(&t->lock, flags); -} - -/* Returns true if the timer is stopped (or was not running), false if - not. Must be called with the timer lock held. */ -static int i2c_stop_timer(struct i2c_adapter * adap) -{ - return (!adap->timer->running || del_timer(&adap->timer->timer)); -} - -static void i2c_handle_timer(unsigned long data) -{ - struct i2c_timer * t = (void *) data; - struct i2c_adapter * adap; - unsigned long flags; - struct i2c_op_q_entry * entry; - unsigned int sequence_match; - - spin_lock_irqsave(&t->lock, flags); - if (t->deleted) { - spin_unlock_irqrestore(&t->lock, flags); - kfree(t); - return; - } - - adap = t->adapter; - t->running = 0; - sequence_match = adap->timer_sequence == t->sequence; - spin_unlock_irqrestore(&t->lock, flags); - - entry = i2c_entry_get(adap); - pr_debug("i2c_handle_timer: %p %p\n", adap, entry); - if (!entry) - return; - - if (sequence_match) { - /* This is the one we expected, call the poll routine. */ - adap->algo->poll(adap, entry, t->next_call_time); - - if (!entry_completed(entry)) - i2c_start_timer(adap, entry); - } else if (entry->use_timer) - /* We raced in timer deletion, just restart the - timer if necessary. */ - i2c_start_timer(adap, entry); - - i2c_entry_put(adap, entry); -} - -void i2c_op_done(struct i2c_adapter *adap, struct i2c_op_q_entry *e) -{ - pr_debug("i2c_op_done: %p %p\n", adap, e); - if (atomic_dec_and_test(&e->completed)) { - /* We are the lucky winner! We get to clean up the - entry. */ - if (e->use_timer) { - unsigned long flags; - struct i2c_timer *t = adap->timer; - spin_lock_irqsave(&t->lock, flags); - if (!i2c_stop_timer(adap)) - /* If we are unable to stop the timer, that - means the timer has gone off but has not - yet run the first part of the handler call. - Increment the sequence so the timer handler - can detect this. */ - adap->timer_sequence++; - spin_unlock_irqrestore(&t->lock, flags); - } - if (e->complete) - e->complete(adap, e); - } - - i2c_entry_put(adap, e); -} - -static void i2c_wait_complete(struct i2c_op_q_entry * entry) -{ - struct completion *done = entry->handler_data; - pr_debug("i2c_wait_complete %p\n", entry); - complete(done); -} - -static void i2c_perform_op_wait(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) +int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num) { - struct completion done; - unsigned long flags; - struct i2c_algorithm *algo = adap->algo; - - pr_debug("i2c_perform_op_wait %p %p\n", adap, entry); - init_completion(&done); - entry->start = NULL; - entry->handler = i2c_wait_complete; - entry->handler_data = &done; - entry->started = 0; - atomic_set(&entry->completed, 1); - entry->result = 0; - entry->use_timer = 0; /* We poll it directly. */ - entry->data = NULL; - atomic_set(&entry->usecount, 1); - spin_lock_irqsave(&adap->q_lock, flags); - list_add_tail(&entry->link, &adap->q); - if (adap->q.next == &entry->link) { - /* Added to the list head, start it */ - spin_unlock_irqrestore(&adap->q_lock, flags); - i2c_start_entry(adap, entry); - } else { - struct completion start; - init_completion(&start); - entry->start = &start; - spin_unlock_irqrestore(&adap->q_lock, flags); - - wait_for_completion_interruptible(&start); - - spin_lock_irqsave(&adap->q_lock, flags); - if (!entry->started) { - /* Operation was interrupted. There - is a race, we can't use the - wait_for_completion return code. */ - entry->result = -ERESTARTSYS; - atomic_set(&entry->completed, 0); - list_del(&entry->link); - } - spin_unlock_irqrestore(&adap->q_lock, flags); - } - - /* Once the operation is started, we will not - interrupt it. */ - while (!entry_completed(entry)) { - unsigned int timeout = entry->call_again_us; - timeout += (USEC_PER_JIFFIE - 1); - timeout /= USEC_PER_JIFFIE; - if (timeout == 0) - timeout = 1; - wait_for_completion_timeout(&done, timeout); - if (entry_completed(entry)) - break; - algo->poll(adap, entry, timeout * USEC_PER_JIFFIE); - } -} + int ret; -static int i2c_transfer_entry(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) -{ - entry->xfer_type = I2C_OP_I2C; - entry->complete = NULL; - if (adap->algo->master_start) { - i2c_perform_op_wait(adap, entry); - return entry->result; - } else if (adap->algo->master_xfer) { - int ret; - dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", - entry->i2c.num); + if (adap->algo->master_xfer) { + dev_dbg(&adap->dev, "master_xfer: with %d msgs.\n", num); down(&adap->bus_lock); - ret = adap->algo->master_xfer(adap, entry->i2c.msgs, - entry->i2c.num); + ret = adap->algo->master_xfer(adap,msgs,num); up(&adap->bus_lock); return ret; @@ -905,45 +600,33 @@ } } -int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num) -{ - struct i2c_op_q_entry *entry; - int rv; - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - entry->i2c.msgs = msgs; - entry->i2c.num = num; - - rv = i2c_transfer_entry(adap, entry); - kfree(entry); - return rv; -} - int i2c_master_send(struct i2c_client *client,const char *buf ,int count) { int ret; struct i2c_adapter *adap=client->adapter; struct i2c_msg msg; - msg.addr = client->addr; - msg.flags = client->flags & I2C_M_TEN; - msg.len = count; - msg.buf = (char *)buf; + if (client->adapter->algo->master_xfer) { + msg.addr = client->addr; + msg.flags = client->flags & I2C_M_TEN; + msg.len = count; + msg.buf = (char *)buf; - dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n", - count); - - ret = i2c_transfer(adap, &msg, 1); - if (ret < 0) - return ret; + dev_dbg(&client->adapter->dev, "master_send: writing %d bytes.\n", + count); + + down(&adap->bus_lock); + ret = adap->algo->master_xfer(adap,&msg,1); + up(&adap->bus_lock); - /* if everything went ok (i.e. 1 msg transmitted), return #bytes - * transmitted, else error code. - */ - return (ret == 1 )? count : ret; + /* if everything went ok (i.e. 1 msg transmitted), return #bytes + * transmitted, else error code. + */ + return (ret == 1 )? count : ret; + } else { + dev_err(&client->adapter->dev, "I2C level transfers not supported\n"); + return -ENOSYS; + } } int i2c_master_recv(struct i2c_client *client, char *buf ,int count) @@ -951,27 +634,31 @@ struct i2c_adapter *adap=client->adapter; struct i2c_msg msg; int ret; + if (client->adapter->algo->master_xfer) { + msg.addr = client->addr; + msg.flags = client->flags & I2C_M_TEN; + msg.flags |= I2C_M_RD; + msg.len = count; + msg.buf = buf; - msg.addr = client->addr; - msg.flags = client->flags & I2C_M_TEN; - msg.flags |= I2C_M_RD; - msg.len = count; - msg.buf = buf; - - dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n", - count); + dev_dbg(&client->adapter->dev, "master_recv: reading %d bytes.\n", + count); - ret = i2c_transfer(adap, &msg, 1); - if (ret < 0) - return ret; - - dev_dbg(&client->adapter->dev, "master_recv: return:%d (count:%d, addr:0x%02x)\n", - ret, count, client->addr); + down(&adap->bus_lock); + ret = adap->algo->master_xfer(adap,&msg,1); + up(&adap->bus_lock); - /* if everything went ok (i.e. 1 msg transmitted), return #bytes - * transmitted, else error code. - */ - return (ret == 1 )? count : ret; + dev_dbg(&client->adapter->dev, "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 + * transmitted, else error code. + */ + return (ret == 1 )? count : ret; + } else { + dev_err(&client->adapter->dev, "I2C level transfers not supported\n"); + return -ENOSYS; + } } @@ -1349,25 +1036,7 @@ } /* Returns the number of read bytes */ -s32 i2c_smbus_read_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_BLOCK_DATA,&data)) - return -1; - else { - for (i = 1; i <= data.block[0]; i++) - values[i-1] = data.block[i]; - return data.block[0]; - } -} - -/* Returns the number of read bytes */ -s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, - u8 *values) +s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 *values) { union i2c_smbus_data data; int i; @@ -1382,334 +1051,185 @@ } } - -static void i2c_smbus_complete_entry(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) -{ - if (entry->result < 0) - return; - - if(entry->result >= 0 && entry->swpec && - entry->smbus.size != I2C_SMBUS_QUICK && - entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA && - (entry->smbus.read_write == I2C_SMBUS_READ || - entry->smbus.size == I2C_SMBUS_PROC_CALL_PEC || - entry->smbus.size == I2C_SMBUS_BLOCK_PROC_CALL_PEC)) { - if(i2c_smbus_check_pec(entry->smbus.addr, - entry->smbus.command, - entry->smbus.size, - entry->partial, - entry->smbus.data)) - entry->result = -EINVAL; - } -} - -static void i2c_smbus_format_entry(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) -{ - entry->swpec = 0; - entry->partial = 0; - entry->smbus.flags &= I2C_M_TEN | I2C_CLIENT_PEC; - if((entry->smbus.flags & I2C_CLIENT_PEC) && - !(i2c_check_functionality(adap, I2C_FUNC_SMBUS_HWPEC_CALC))) { - entry->swpec = 1; - if(entry->smbus.read_write == I2C_SMBUS_READ && - entry->smbus.size == I2C_SMBUS_BLOCK_DATA) - entry->smbus.size = I2C_SMBUS_BLOCK_DATA_PEC; - else if(entry->smbus.size == I2C_SMBUS_PROC_CALL) - entry->smbus.size = I2C_SMBUS_PROC_CALL_PEC; - else if(entry->smbus.size == I2C_SMBUS_BLOCK_PROC_CALL) { - unsigned char *data = entry->smbus.data->block; - i2c_smbus_add_pec(entry->smbus.addr, - entry->smbus.command, - I2C_SMBUS_BLOCK_DATA, - entry->smbus.data); - entry->partial = data[data[0] + 1]; - entry->smbus.size = I2C_SMBUS_BLOCK_PROC_CALL_PEC; - } else if(entry->smbus.read_write == I2C_SMBUS_WRITE && - entry->smbus.size != I2C_SMBUS_QUICK && - entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA) - entry->smbus.size = - i2c_smbus_add_pec(entry->smbus.addr, - entry->smbus.command, - entry->smbus.size, - entry->smbus.data); - } - - entry->complete = i2c_smbus_complete_entry; -} - -static void i2c_smbus_emu_complete(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) -{ - unsigned char *msgbuf0 = entry->i2c.msgs[0].buf; - unsigned char *msgbuf1 = entry->i2c.msgs[1].buf; - int i; - - if (entry->smbus.read_write != I2C_SMBUS_READ) - return; - - switch(entry->smbus.size) { - case I2C_SMBUS_BYTE: - entry->smbus.data->byte = msgbuf0[0]; - break; - case I2C_SMBUS_BYTE_DATA: - entry->smbus.data->byte = msgbuf1[0]; - break; - case I2C_SMBUS_WORD_DATA: - case I2C_SMBUS_PROC_CALL: - entry->smbus.data->word = msgbuf1[0]|(msgbuf1[1] << 8); - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - /* fixed at 32 for now */ - entry->smbus.data->block[0] = I2C_SMBUS_I2C_BLOCK_MAX; - for (i = 0; i < I2C_SMBUS_I2C_BLOCK_MAX; i++) - entry->smbus.data->block[i+1] = msgbuf1[i]; - break; - } - - entry->xfer_type = I2C_OP_SMBUS; - i2c_smbus_complete_entry(adap, entry); -} - -static int i2c_smbus_emu_format(struct i2c_adapter *adap, - struct i2c_op_q_entry * entry) -{ - /* So we need to generate a series of msgs. In the case of - writing, we need to use only one message; when reading, we - need two. We initialize most things with sane defaults, to - keep the code below somewhat simpler. */ - unsigned char *msgbuf0 = entry->msgbuf0; - unsigned char *msgbuf1 = entry->msgbuf1; - int num = entry->smbus.read_write == I2C_SMBUS_READ?2:1; - struct i2c_msg *msg = entry->msg; +/* Simulate a SMBus command using the i2c protocol + No checking of parameters is done! */ +static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, + unsigned short flags, + char read_write, u8 command, int size, + union i2c_smbus_data * data) +{ + /* So we need to generate a series of msgs. In the case of writing, we + need to use only one message; when reading, we need two. We initialize + most things with sane defaults, to keep the code below somewhat + simpler. */ + unsigned char msgbuf0[34]; + unsigned char msgbuf1[34]; + int num = read_write == I2C_SMBUS_READ?2:1; + struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, + { addr, flags | I2C_M_RD, 0, msgbuf1 } + }; int i; - entry->i2c.msgs = msg; - entry->i2c.msgs[0].buf = msgbuf0; - entry->i2c.msgs[1].buf = msgbuf1; - - msg[0].addr = entry->smbus.addr; - msg[0].flags = entry->smbus.flags; - msg[0].len = 1; - msg[1].addr = entry->smbus.addr; - msg[1].flags = entry->smbus.flags | I2C_M_RD; - msg[1].len = 1; - - msgbuf0[0] = entry->smbus.command; - switch(entry->smbus.size) { + msgbuf0[0] = command; + switch(size) { case I2C_SMBUS_QUICK: msg[0].len = 0; /* Special case: The read/write field is used as data */ - msg[0].flags = (entry->smbus.flags | - ((entry->smbus.read_write==I2C_SMBUS_READ) - ? I2C_M_RD : 0)); + msg[0].flags = flags | (read_write==I2C_SMBUS_READ)?I2C_M_RD:0; num = 1; break; case I2C_SMBUS_BYTE: - if (entry->smbus.read_write == I2C_SMBUS_READ) { + if (read_write == I2C_SMBUS_READ) { /* Special case: only a read! */ - msg[0].flags = I2C_M_RD | entry->smbus.flags; + msg[0].flags = I2C_M_RD | flags; num = 1; } break; case I2C_SMBUS_BYTE_DATA: - if (entry->smbus.read_write == I2C_SMBUS_READ) + if (read_write == I2C_SMBUS_READ) msg[1].len = 1; else { msg[0].len = 2; - msgbuf0[1] = entry->smbus.data->byte; + msgbuf0[1] = data->byte; } break; case I2C_SMBUS_WORD_DATA: - if (entry->smbus.read_write == I2C_SMBUS_READ) + if (read_write == I2C_SMBUS_READ) msg[1].len = 2; else { msg[0].len=3; - msgbuf0[1] = entry->smbus.data->word & 0xff; - msgbuf0[2] = (entry->smbus.data->word >> 8) & 0xff; + msgbuf0[1] = data->word & 0xff; + msgbuf0[2] = (data->word >> 8) & 0xff; } break; case I2C_SMBUS_PROC_CALL: num = 2; /* Special case */ - entry->smbus.read_write = I2C_SMBUS_READ; + read_write = I2C_SMBUS_READ; msg[0].len = 3; msg[1].len = 2; - msgbuf0[1] = entry->smbus.data->word & 0xff; - msgbuf0[2] = (entry->smbus.data->word >> 8) & 0xff; + msgbuf0[1] = data->word & 0xff; + msgbuf0[2] = (data->word >> 8) & 0xff; break; case I2C_SMBUS_BLOCK_DATA: case I2C_SMBUS_BLOCK_DATA_PEC: - if (entry->smbus.read_write == I2C_SMBUS_READ) { - dev_err(&adap->dev, "Block read not supported " + if (read_write == I2C_SMBUS_READ) { + dev_err(&adapter->dev, "Block read not supported " "under I2C emulation!\n"); return -1; } else { - msg[0].len = entry->smbus.data->block[0] + 2; + msg[0].len = data->block[0] + 2; if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { - dev_err(&adap->dev, - "smbus_access called with " + dev_err(&adapter->dev, "smbus_access called with " "invalid block write size (%d)\n", - entry->smbus.data->block[0]); + data->block[0]); return -1; } - if(entry->smbus.size == I2C_SMBUS_BLOCK_DATA_PEC) + if(size == I2C_SMBUS_BLOCK_DATA_PEC) (msg[0].len)++; for (i = 1; i <= msg[0].len; i++) - msgbuf0[i] = entry->smbus.data->block[i-1]; + msgbuf0[i] = data->block[i-1]; } break; case I2C_SMBUS_BLOCK_PROC_CALL: case I2C_SMBUS_BLOCK_PROC_CALL_PEC: - dev_dbg(&adap->dev, "Block process call not supported " + dev_dbg(&adapter->dev, "Block process call not supported " "under I2C emulation!\n"); return -1; case I2C_SMBUS_I2C_BLOCK_DATA: - if (entry->smbus.read_write == I2C_SMBUS_READ) { + if (read_write == I2C_SMBUS_READ) { msg[1].len = I2C_SMBUS_I2C_BLOCK_MAX; } else { - msg[0].len = entry->smbus.data->block[0] + 1; + msg[0].len = data->block[0] + 1; if (msg[0].len > I2C_SMBUS_I2C_BLOCK_MAX + 1) { - dev_err(&adap->dev, - "i2c_smbus_xfer_emulated called with " + dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with " "invalid block write size (%d)\n", - entry->smbus.data->block[0]); + data->block[0]); return -1; } - for (i = 1; i <= entry->smbus.data->block[0]; i++) - msgbuf0[i] = entry->smbus.data->block[i]; + for (i = 1; i <= data->block[0]; i++) + msgbuf0[i] = data->block[i]; } break; default: - dev_err(&adap->dev, - "smbus_access called with invalid size (%d)\n", - entry->smbus.size); + dev_err(&adapter->dev, "smbus_access called with invalid size (%d)\n", + size); return -1; } - entry->xfer_type = I2C_OP_I2C; - entry->i2c.msgs = msg; - entry->i2c.num = num; - entry->complete = i2c_smbus_emu_complete; + if (i2c_transfer(adapter, msg, num) < 0) + return -1; + + if (read_write == I2C_SMBUS_READ) + switch(size) { + case I2C_SMBUS_BYTE: + data->byte = msgbuf0[0]; + break; + case I2C_SMBUS_BYTE_DATA: + data->byte = msgbuf1[0]; + break; + case I2C_SMBUS_WORD_DATA: + 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; } -/* Simulate a SMBus command using the i2c protocol - No checking of parameters is done! */ -static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry) - -{ - if (i2c_smbus_emu_format(adap, entry)) - return -EINVAL; - if (i2c_transfer_entry(adap, entry) < 0) - return -EINVAL; - - return entry->result; -} - -s32 i2c_smbus_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, +s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { - struct i2c_op_q_entry *entry; - struct i2c_algorithm *algo = adap->algo; - int result; - - - entry = kmalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - entry->xfer_type = I2C_OP_SMBUS; - entry->smbus.addr = addr; - entry->smbus.flags = flags; - entry->smbus.read_write = read_write; - entry->smbus.command = command; - entry->smbus.size = size; - entry->smbus.data = data; - - i2c_smbus_format_entry(adap, entry); - - if (algo->smbus_start) { - i2c_perform_op_wait(adap, entry); - } else if (algo->smbus_xfer) { - down(&adap->bus_lock); - entry->result = adap->algo->smbus_xfer(adap, - entry->smbus.addr, - entry->smbus.flags, - entry->smbus.read_write, - entry->smbus.command, - entry->smbus.size, - entry->smbus.data); - up(&adap->bus_lock); - } else { - i2c_smbus_xfer_emulated(adap, entry); - } - - result = entry->result; - kfree(entry); - return result; -} - -int i2c_non_blocking_capable(struct i2c_adapter *adap) -{ - return adap->algo->poll != NULL; -} - -void i2c_poll(struct i2c_client *client, - unsigned int us_since_last_call) -{ - struct i2c_adapter *adap = client->adapter; - struct i2c_op_q_entry *entry; - - entry = i2c_entry_get(adap); - if (!entry) - return; - adap->algo->poll(adap, entry, us_since_last_call); - i2c_entry_put(adap, entry); -} - -int i2c_non_blocking_op(struct i2c_client *client, - struct i2c_op_q_entry *entry) -{ - unsigned long flags; - struct i2c_adapter *adap = client->adapter; - - if (!i2c_non_blocking_capable(adap)) - return -ENOSYS; - - entry->smbus.addr = client->addr; - entry->smbus.flags = client->flags; + s32 res; + int swpec = 0; + u8 partial = 0; + + flags &= I2C_M_TEN | I2C_CLIENT_PEC; + if((flags & I2C_CLIENT_PEC) && + !(i2c_check_functionality(adapter, I2C_FUNC_SMBUS_HWPEC_CALC))) { + swpec = 1; + if(read_write == I2C_SMBUS_READ && + size == I2C_SMBUS_BLOCK_DATA) + size = I2C_SMBUS_BLOCK_DATA_PEC; + else if(size == I2C_SMBUS_PROC_CALL) + size = I2C_SMBUS_PROC_CALL_PEC; + else if(size == I2C_SMBUS_BLOCK_PROC_CALL) { + i2c_smbus_add_pec(addr, command, + I2C_SMBUS_BLOCK_DATA, data); + partial = data->block[data->block[0] + 1]; + size = I2C_SMBUS_BLOCK_PROC_CALL_PEC; + } else if(read_write == I2C_SMBUS_WRITE && + size != I2C_SMBUS_QUICK && + size != I2C_SMBUS_I2C_BLOCK_DATA) + size = i2c_smbus_add_pec(addr, command, size, data); + } + + if (adapter->algo->smbus_xfer) { + down(&adapter->bus_lock); + res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, + command,size,data); + up(&adapter->bus_lock); + } else + res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, + command,size,data); - if (entry->xfer_type == I2C_OP_SMBUS) { - i2c_smbus_format_entry(adap, entry); - if (!adap->algo->smbus_start) { - if (i2c_smbus_emu_format(adap, entry)) - return -EINVAL; - } + 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; } - - entry->start = NULL; - entry->started = 0; - atomic_set(&entry->completed, 1); - entry->result = 0; - entry->use_timer = 1; /* Let the timer code poll it. */ - entry->data = NULL; - atomic_set(&entry->usecount, 1); - - spin_lock_irqsave(&adap->q_lock, flags); - list_add_tail(&entry->link, &adap->q); - if (adap->q.next == &entry->link) { - /* Added to the list head, start it */ - spin_unlock_irqrestore(&adap->q_lock, flags); - i2c_start_entry(adap, entry); - } else - spin_unlock_irqrestore(&adap->q_lock, flags); - return 0; + return res; } + /* You should always define `functionality'; the 'else' is just for backward compatibility. */ u32 i2c_get_functionality (struct i2c_adapter *adap) @@ -1737,7 +1257,6 @@ EXPORT_SYMBOL(i2c_clients_command); EXPORT_SYMBOL(i2c_check_addr); -EXPORT_SYMBOL(i2c_op_done); EXPORT_SYMBOL(i2c_master_send); EXPORT_SYMBOL(i2c_master_recv); EXPORT_SYMBOL(i2c_control); @@ -1756,13 +1275,8 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data); EXPORT_SYMBOL(i2c_smbus_write_word_data); EXPORT_SYMBOL(i2c_smbus_write_block_data); -EXPORT_SYMBOL(i2c_smbus_read_block_data); EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); -EXPORT_SYMBOL(i2c_non_blocking_capable); -EXPORT_SYMBOL(i2c_poll); -EXPORT_SYMBOL(i2c_non_blocking_op); - EXPORT_SYMBOL(i2c_get_functionality); EXPORT_SYMBOL(i2c_check_functionality); diff -Naur linux-2.6.11-rc4-mm1/include/linux/i2c.h linux-2.6.11-rc4-mm1-bttv/include/linux/i2c.h --- linux-2.6.11-rc4-mm1/include/linux/i2c.h 2005-02-23 10:19:43.316206072 -0800 +++ linux-2.6.11-rc4-mm1-bttv/include/linux/i2c.h 2005-02-24 10:37:01.501209816 -0800 @@ -32,11 +32,7 @@ #include #include #include /* for struct device */ -#include -#include -#include #include -#include /* --- General options ------------------------------------------------ */ @@ -47,7 +43,6 @@ struct i2c_driver; struct i2c_client_address_data; union i2c_smbus_data; -struct i2c_op_q_entry; /* * The master routines are the ones normally used to transmit data to devices @@ -60,7 +55,7 @@ /* Transfer num messages. */ -extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,int num); +extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],int num); /* * Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor. @@ -97,30 +92,9 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client, u8 command, u8 length, u8 *values); -extern s32 i2c_smbus_read_block_data(struct i2c_client * client, - u8 command, u8 *values); extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, u8 command, u8 *values); -/* Non-blocking interface. The user should fill out the public - portions of the entry structure. All data in the entry structure - should be guaranteed to be available until the handler callback is - called with the entry. */ -typedef void (*i2c_op_done_cb)(struct i2c_op_q_entry *entry); - -extern int i2c_non_blocking_op(struct i2c_client *client, - struct i2c_op_q_entry *entry); - -/* Can the adapter do non-blocking operations? */ -extern int i2c_non_blocking_capable(struct i2c_adapter *adap); - -/* Poll the i2c interface. This should only be called in a situation - where scheduling and interrupts are off. You should put the amount - of microseconds between calls in us_since_last_call. */ -extern void i2c_poll(struct i2c_client *client, - unsigned int us_since_last_call); - - /* * A driver is capable of handling one or more physical devices present on * I2C adapters. This information is used to inform the driver of adapter @@ -204,33 +178,6 @@ } /* - * About locking and the non-blocking interface. - * - * The poll operations are called single-threaded (along with the - * xxx_start operations), so if the driver is only polled then there - * is no need to do any locking. If you are using interrupts, then - * the timer operations and interrupts can race and you need to lock - * appropriately. - * - * i2c_op_done() can be called multiple times on the same entry (as - * long as each one has a get operation). This handles poll and - * interrupt races calling i2c_op_done(). It will do the right thing. - */ - -/* Called from an non-blocking interface to get the current working - entry. Returns NULL if there is none. This is primarily for - interrupt handlers to determine what they should be working on. - Note that if you call i2c_entry_get() and get a non-null entry, you - must call i2c_entry_put() on it. */ -struct i2c_op_q_entry *i2c_entry_get(struct i2c_adapter * adap); -void i2c_entry_put(struct i2c_adapter * adap, - struct i2c_op_q_entry * entry); - -/* Called from an non-blocking interface to report that an operation - has completed. Can be called from interrupt context. */ -void i2c_op_done(struct i2c_adapter *adap, struct i2c_op_q_entry *entry); - -/* * The following structs are for those who like to implement new bus drivers: * i2c_algorithm is the interface to a class of hardware solutions which can * be addressed using the same bus algorithms - i.e. bit-banging or the PCF8584 @@ -240,40 +187,15 @@ char name[32]; /* textual description */ unsigned int id; - /* If an adapter algorithm can't do I2C-level access, set master_xfer + /* If an adapter algorithm can't to I2C-level access, set master_xfer to NULL. If an adapter algorithm can do SMBus access, set smbus_xfer. If set to NULL, the SMBus protocol is simulated using common I2C messages */ - int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs, - int num); - int (*smbus_xfer)(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data); - - /* These are like the previous calls, but they will only start - the operation. The poll call will be called periodically - to drive the operation of the bus. Each of these calls - should set the result on an error, and set the timeout as - necessary. Note that even interrupt driven drivers need to - poll so they can time out operations. When the operation - is complete, these should call i2c_op_done(). Note that - all the data structures passed in are guaranteed to be kept - around until the operation completes. These may be called - from interrupt context. If the start operation fails, this - should set the result and call i2c_op_done(). */ - void (*master_start)(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry); - void (*smbus_start)(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry); - /* us_since_last_poll is the amount of time since the last - time poll was called. Note that this may be *less* than the - time you requested, so always use this number and don't - assume it's the one you gave it. This time is approximate - and is only guaranteed to be >= the time since the last - poll. The value may be zero. */ - void (*poll)(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry, - unsigned int us_since_last_poll); + int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[], + int num); + int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data * data); /* --- these optional/future use for some adapter types.*/ int (*slave_send)(struct i2c_adapter *,char*,int); @@ -287,21 +209,6 @@ }; /* - * The timer has it's own separately allocated data structure because - * it needs to be able to exist even if the adapter is deleted (due to - * timer cancellation races). - */ -struct i2c_timer { - spinlock_t lock; - int deleted; - struct timer_list timer; - int running; - unsigned int next_call_time; - struct i2c_adapter *adapter; - unsigned int sequence; -}; - -/* * i2c_adapter is the structure used to identify a physical i2c bus along * with the access algorithms necessary to access it. */ @@ -318,15 +225,8 @@ int (*client_unregister)(struct i2c_client *); /* data fields that are valid for all devices */ - struct list_head q; - spinlock_t q_lock; - struct semaphore bus_lock; - - /* Used to time non-blocking operations. The sequence is used - to handle race conditions in the timer handler. */ - struct i2c_timer *timer; - unsigned int timer_sequence; + struct semaphore clist_lock; int timeout; int retries; @@ -339,14 +239,9 @@ #endif /* def CONFIG_PROC_FS */ int nr; - - struct semaphore clist_lock; struct list_head clients; - struct list_head list; - char name[I2C_NAME_SIZE]; - struct completion dev_released; struct completion class_dev_released; }; @@ -497,90 +392,6 @@ __u8 *buf; /* pointer to msg data */ }; -/* - * Hold a queue of I2C operations to perform, and used to pass data - * around. - */ -#define I2C_OP_I2C 0 -#define I2C_OP_SMBUS 1 -struct i2c_op_q_entry { - /* The result will be set to the result of the operation when - it completes. */ - s32 result; - - /**************************************************************/ - /* Public interface. The user should set these up (and the - proper structure below). */ - int xfer_type; - - /* Handler may be called from interrupt context, so be - careful. */ - i2c_op_done_cb handler; - void *handler_data; - - /* Note that this is not a union because an smbus operation - may be converted into an i2c operation (thus both - structures will be used). The data in these may be changd - by the driver. */ - struct { - struct i2c_msg *msgs; - int num; - } i2c; - struct { - /* Addr and flags are filled in by the non-blocking - send routine that takes a client. */ - u16 addr; - unsigned short flags; - - char read_write; - u8 command; - - /* Note that the size is *not* the length of the data. - It is the transaction type, like I2C_SMBUS_QUICK - and the ones after that below. If this is a block - transaction, the length of the rest of the data is - in the first byte of the data, for both transmit - and receive. */ - int size; - union i2c_smbus_data *data; - } smbus; - - /**************************************************************/ - /* For use by the bus interface. The bus interface sets the - timeout in microseconds until the next poll operation. - This *must* be set in the start operation. The time_left - and data can be used for anything the bus interface likes. - data will be set to NULL before being started so the bus - interface can use that to tell if it has been set up - yet. */ - unsigned int call_again_us; - long time_left; - void *data; - - /**************************************************************/ - /* Internals */ - struct list_head link; - struct completion *start; - atomic_t completed; - unsigned int started : 1; - unsigned int use_timer : 1; - u8 swpec; - u8 partial; - void (*complete)(struct i2c_adapter *adap, - struct i2c_op_q_entry *entry); - - /* It's wierd, but we use a usecount to track if an q entry is - in use and when it should be reported back to the user. */ - atomic_t usecount; - - /* These are here for SMBus emulation over I2C. I don't like - them taking this much room in the data structure, but they - need to be available in this case. */ - unsigned char msgbuf0[34]; - unsigned char msgbuf1[34]; - struct i2c_msg msg[2]; -}; - /* To determine what functionality is present */ #define I2C_FUNC_I2C 0x00000001 @@ -609,22 +420,22 @@ #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) -#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \ - I2C_FUNC_SMBUS_WRITE_BYTE_DATA) -#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \ - I2C_FUNC_SMBUS_WRITE_WORD_DATA) -#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ - I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) -#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ - 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_BYTE I2C_FUNC_SMBUS_READ_BYTE | \ + I2C_FUNC_SMBUS_WRITE_BYTE +#define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \ + I2C_FUNC_SMBUS_WRITE_BYTE_DATA +#define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \ + I2C_FUNC_SMBUS_WRITE_WORD_DATA +#define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA +#define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \ + 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 @@ -633,14 +444,14 @@ #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 | \ - I2C_FUNC_SMBUS_BYTE_DATA | \ - I2C_FUNC_SMBUS_WORD_DATA | \ - I2C_FUNC_SMBUS_PROC_CALL | \ - I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ - I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \ - I2C_FUNC_SMBUS_I2C_BLOCK) +#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \ + I2C_FUNC_SMBUS_BYTE | \ + I2C_FUNC_SMBUS_BYTE_DATA | \ + I2C_FUNC_SMBUS_WORD_DATA | \ + I2C_FUNC_SMBUS_PROC_CALL | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \ + I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \ + I2C_FUNC_SMBUS_I2C_BLOCK /* * Data for SMBus Messages