Index: linux-2.6.30/drivers/i2c/busses/i2c-i801.c =================================================================== --- linux-2.6.30.orig/drivers/i2c/busses/i2c-i801.c +++ linux-2.6.30/drivers/i2c/busses/i2c-i801.c @@ -55,6 +55,14 @@ /* 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 @@ -96,7 +104,8 @@ #define SMBHSTCNT_KILL 2 /* Other settings */ -#define MAX_TIMEOUT 100 +#define MAX_TIMEOUT_US 100000 +#define RETRY_TIME_US 500 /* Retry minimum is 500us */ #define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ /* I801 command constants */ @@ -126,6 +135,26 @@ SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ SMBHSTSTS_INTR) +enum i801_drv_state { + I801_NORMAL = 0, + I801_TIMEOUT_RECOVERY, + I801_WAIT_INTR +}; + +struct i801_i2c_data { + int i; + int len; + unsigned char hostc; + int block; + int full_block; + int hwpec; + int xact; + int hststs; + int finished; + enum i801_drv_state state; +}; +struct i801_i2c_data i801_data; + static unsigned long i801_smba; static unsigned char i801_original_hstcfg; static struct pci_driver i801_driver; @@ -167,29 +196,10 @@ static int i801_check_pre(void) } /* Convert the status register to an error code, and clear it. */ -static int i801_check_post(int status, int timeout) +static int i801_check_post(int status) { int result = 0; - /* If the SMBus is still busy, we give up */ - if (timeout) { - dev_err(&I801_dev->dev, "Transaction timeout\n"); - /* try to stop the current command */ - dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); - outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); - msleep(1); - outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); - - /* Check if it worked */ - status = inb_p(SMBHSTSTS); - if ((status & SMBHSTSTS_HOST_BUSY) || - !(status & SMBHSTSTS_FAILED)) - dev_err(&I801_dev->dev, - "Failed terminating the transaction\n"); - outb_p(STATUS_FLAGS, SMBHSTSTS); - return -ETIMEDOUT; - } - if (status & SMBHSTSTS_FAILED) { result = -EIO; dev_err(&I801_dev->dev, "Transaction failed\n"); @@ -217,164 +227,252 @@ static int i801_check_post(int status, i return result; } -static int i801_transaction(int xact) +static void i801_finish(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + struct i801_i2c_data *d) { - int status; - int result; - int timeout = 0; + d->finished = 1; - result = i801_check_pre(); - if (result < 0) - return result; + if (d->block && entry->smbus.size == I2C_SMBUS_I2C_BLOCK_DATA + && entry->smbus.read_write == I2C_SMBUS_WRITE) + /* restore saved configuration register value */ + pci_write_config_byte(I801_dev, SMBHSTCFG, d->hostc); + + /* + * Some BIOSes don't like it when PEC is enabled at reboot or resume + * time, so we forcibly disable it after every transaction. Turn off + * E32B for the same reason. + */ + if (d->hwpec) + outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), + SMBAUXCTL); + + if (entry->result < 0) + return; + + if ((d->full_block) && (entry->smbus.read_write == I2C_SMBUS_READ)) { + int i; + + /* + * A full block transfer, make sure to get the length and + * the data. + */ + d->len = inb_p(SMBHSTDAT0); + if (d->len < 1 || d->len > I2C_SMBUS_BLOCK_MAX) + entry->result = -EIO; + else { + entry->smbus.data->block[0] = d->len; + for (i = 0; i < d->len; i++) + entry->smbus.data->block[i + 1] = + inb_p(SMBBLKDAT); + } + } + + if (d->block || + ((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; + } +} - /* the current contents of SMBHSTCNT can be overwritten, since PEC, - * INTREN, SMBSCMD are passed in xact */ - outb_p(xact | I801_START, SMBHSTCNT); - - /* We will always wait for a fraction of a second! */ - do { - msleep(1); - status = inb_p(SMBHSTSTS); - } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT)); +static void i801_timeout_recovery_poll(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + struct i801_i2c_data *d) +{ + outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); + + /* Check if it worked */ + d->hststs = inb_p(SMBHSTSTS); + if ((d->hststs & SMBHSTSTS_HOST_BUSY) || + !(d->hststs & SMBHSTSTS_FAILED)) + dev_err(&I801_dev->dev, + "Failed terminating the transaction\n"); + outb_p(STATUS_FLAGS, SMBHSTSTS); + + entry->result = -ETIMEDOUT; + d->state = I801_NORMAL; + i801_finish(adap, entry, d); +} + +static void i801_start_timeout_recovery(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + struct i801_i2c_data *d) +{ + dev_err(&I801_dev->dev, "Transaction timeout\n"); + /* try to stop the current command */ + dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); + outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); + d->state = I801_TIMEOUT_RECOVERY; +} + +static void i801_block_poll_wait_intr(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + struct i801_i2c_data *d) +{ + /* wait for INTR bit as advised by Intel */ + d->hststs = inb_p(SMBHSTSTS); + if (d->hststs & SMBHSTSTS_INTR) { + d->state = I801_NORMAL; + outb_p(d->hststs, SMBHSTSTS); + i801_finish(adap, entry, d); + } else if (entry->time_left <= 0) { + /* Timed out */ + d->state = I801_NORMAL; + outb_p(d->hststs, SMBHSTSTS); + entry->result = -EIO; + dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); + } +} + +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 & SMBHSTSTS_HOST_BUSY)) { + entry->result = i801_check_post(d->hststs); + if (d->hwpec) { + d->state = I801_WAIT_INTR; + entry->time_left = MAX_TIMEOUT_US; + i801_block_poll_wait_intr(adap, entry, d); + } else + i801_finish(adap, entry, d); + } else if (entry->time_left <= 0) + i801_start_timeout_recovery(adap, entry, d); +} - result = i801_check_post(status, timeout > MAX_TIMEOUT); +static int i801_transaction_start(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + struct i801_i2c_data *d) +{ + int result = i801_check_pre(); if (result < 0) return result; - outb_p(SMBHSTSTS_INTR, SMBHSTSTS); + outb_p(d->xact | I801_START, SMBHSTCNT); return 0; } -/* wait for INTR bit as advised by Intel */ -static void i801_wait_hwpec(void) +static int i801_full_block(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + struct i801_i2c_data *d) { - int timeout = 0; - int status; + int i; - do { - msleep(1); - status = inb_p(SMBHSTSTS); - } while ((!(status & SMBHSTSTS_INTR)) - && (timeout++ < MAX_TIMEOUT)); + d->full_block = 1; - if (timeout > MAX_TIMEOUT) - dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); + inb_p(SMBHSTCNT); /* reset the data buffer index */ + + /* Use 32-byte buffer to process this transaction */ + if (entry->smbus.read_write == I2C_SMBUS_WRITE) { + outb_p(d->len, SMBHSTDAT0); + for (i = 0; i < d->len; i++) + outb_p(entry->smbus.data->block[i + 1], SMBBLKDAT); + } + + d->xact = I801_BLOCK_DATA | ENABLE_INT9; + if (d->hwpec) + d->xact |= I801_PEC_EN; - outb_p(status, SMBHSTSTS); + return i801_transaction_start(adap, entry, d); } -static int i801_block_transaction_by_block(union i2c_smbus_data *data, - char read_write, int hwpec) +static int i801_block_next_byte(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + struct i801_i2c_data *d) { - int i, len; + int smbcmd; int status; - inb_p(SMBHSTCNT); /* reset the data buffer index */ - - /* Use 32-byte buffer to process this transaction */ - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - outb_p(len, SMBHSTDAT0); - for (i = 0; i < len; i++) - outb_p(data->block[i+1], SMBBLKDAT); + if (d->i > d->len) { + if (d->hwpec) { + d->state = I801_WAIT_INTR; + entry->time_left = MAX_TIMEOUT_US; + i801_block_poll_wait_intr(adap, entry, d); + } else + i801_finish(adap, entry, d); + return 0; } - status = i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 | - I801_PEC_EN * hwpec); + if (d->i == d->len && entry->smbus.read_write == I2C_SMBUS_READ) { + if (entry->smbus.command == I2C_SMBUS_I2C_BLOCK_DATA) + smbcmd = I801_I2C_BLOCK_LAST; + else + smbcmd = I801_BLOCK_LAST; + } else { + if (entry->smbus.command == I2C_SMBUS_I2C_BLOCK_DATA + && entry->smbus.read_write == I2C_SMBUS_READ) + smbcmd = I801_I2C_BLOCK_DATA; + else + smbcmd = I801_BLOCK_DATA; + } + outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); + + /* Make sure the SMBus host is ready to start transmitting */ + d->hststs = inb_p(SMBHSTSTS); + status = i801_check_post(d->hststs); if (status) return status; - if (read_write == I2C_SMBUS_READ) { - len = inb_p(SMBHSTDAT0); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - - data->block[0] = len; - for (i = 0; i < len; i++) - data->block[i + 1] = inb_p(SMBBLKDAT); - } + if (d->i == 1) + outb_p(d->hststs | I801_START, SMBHSTCNT); return 0; } -static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data, - char read_write, int command, - int hwpec) +/* 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) { - int i, len; - int smbcmd; int status; - int result; - int timeout; - result = i801_check_pre(); - if (result < 0) - return result; - - len = data->block[0]; - - if (read_write == I2C_SMBUS_WRITE) { - outb_p(len, SMBHSTDAT0); - outb_p(data->block[1], SMBBLKDAT); - } - - for (i = 1; i <= len; i++) { - if (i == len && read_write == I2C_SMBUS_READ) { - if (command == I2C_SMBUS_I2C_BLOCK_DATA) - smbcmd = I801_I2C_BLOCK_LAST; - else - smbcmd = I801_BLOCK_LAST; - } else { - if (command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_READ) - smbcmd = I801_I2C_BLOCK_DATA; - else - smbcmd = I801_BLOCK_DATA; - } - outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); - - if (i == 1) - outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); + d->hststs = inb_p(SMBHSTSTS); + if (!(d->hststs & SMBHSTSTS_BYTE_DONE)) { + /* Not ready yet */ + if (entry->time_left <= 0) + i801_start_timeout_recovery(adap, entry, d); + return; + } - /* We will always wait for a fraction of a second! */ - timeout = 0; - do { - msleep(1); - status = inb_p(SMBHSTSTS); - } - while ((!(status & SMBHSTSTS_BYTE_DONE)) - && (timeout++ < MAX_TIMEOUT)); + status = i801_check_post(d->hststs); + if (status) { + entry->result = status; + return; + } - result = i801_check_post(status, timeout > MAX_TIMEOUT); - if (result < 0) - return result; - - if (i == 1 && read_write == I2C_SMBUS_READ - && command != I2C_SMBUS_I2C_BLOCK_DATA) { - len = inb_p(SMBHSTDAT0); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { - dev_err(&I801_dev->dev, - "Illegal SMBus block read size %d\n", - len); - /* Recover */ - while (inb_p(SMBHSTSTS) & SMBHSTSTS_HOST_BUSY) - outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS); - outb_p(SMBHSTSTS_INTR, SMBHSTSTS); - return -EPROTO; - } - data->block[0] = len; - } + if (d->i == 1 && entry->smbus.read_write == I2C_SMBUS_READ + && entry->smbus.command != I2C_SMBUS_I2C_BLOCK_DATA) { + /* When reading, the first byte is the length. */ + d->len = inb_p(SMBHSTDAT0); + if ((d->len < 1) || (d->len > 32)) { + entry->result = -EPROTO; + return; + } else + entry->smbus.data->block[0] = d->len; + } - /* 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); + /* 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); - /* signals SMBBLKDAT ready */ - outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS); - } + /* signals SMBBLKDAT ready */ + outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS); - return 0; + (d->i)++; + entry->result = i801_block_next_byte(adap, entry, d); } static int i801_set_block_buffer_mode(void) @@ -385,158 +483,203 @@ static int i801_set_block_buffer_mode(vo return 0; } -/* Block transaction function */ -static int i801_block_transaction(union i2c_smbus_data *data, char read_write, - int command, int hwpec) +static int i801_block_start(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + struct i801_i2c_data *d) { - int result = 0; - unsigned char hostc; - - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (read_write == I2C_SMBUS_WRITE) { + 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, &hostc); + pci_read_config_byte(I801_dev, SMBHSTCFG, &d->hostc); pci_write_config_byte(I801_dev, SMBHSTCFG, - hostc | SMBHSTCFG_I2C_EN); + d->hostc | SMBHSTCFG_I2C_EN); } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) { dev_err(&I801_dev->dev, "I2C block read is unsupported!\n"); - return -EOPNOTSUPP; + return -EINVAL; } } - if (read_write == I2C_SMBUS_WRITE - || command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (data->block[0] < 1) - data->block[0] = 1; - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) - data->block[0] = I2C_SMBUS_BLOCK_MAX; - } else { - data->block[0] = 32; /* max for SMBus block reads */ - } + if (entry->smbus.read_write == I2C_SMBUS_WRITE + || entry->smbus.command == I2C_SMBUS_I2C_BLOCK_DATA) { + d->len = entry->smbus.data->block[0]; + if (d->len < 1) + d->len = 1; + if (d->len > I2C_SMBUS_BLOCK_MAX) + d->len = I2C_SMBUS_BLOCK_MAX; + } else + d->len = 32; /* max for SMBus block reads */ if ((i801_features & FEATURE_BLOCK_BUFFER) - && !(command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_READ) - && i801_set_block_buffer_mode() == 0) - result = i801_block_transaction_by_block(data, read_write, - hwpec); - else - result = i801_block_transaction_byte_by_byte(data, read_write, - command, hwpec); + && !(entry->smbus.command == I2C_SMBUS_I2C_BLOCK_DATA + && entry->smbus.read_write == I2C_SMBUS_READ) + && i801_set_block_buffer_mode() == 0) + return i801_full_block(adap, entry, d); + else { + d->i = 1; + if (entry->smbus.read_write == I2C_SMBUS_WRITE) { + outb_p(d->len, SMBHSTDAT0); + outb_p(entry->smbus.data->block[1], SMBBLKDAT); + } + return i801_block_next_byte(adap, entry, d); + } +} - if (result == 0 && hwpec) - i801_wait_hwpec(); +/* 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; - if (command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_WRITE) { - /* restore saved configuration register value */ - pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); + dev_dbg(&I801_dev->dev, "Poll call for %p %p at %ld\n", adap, entry, + jiffies); + + if (!d) + /* The entry hasn't been started yet. */ + return; + + 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); + return; + } + + /* Decrement timeout */ + entry->time_left -= us_since_last_poll; + + /* Wait a jiffie normally. */ + entry->call_again_us = RETRY_TIME_US; + + if (d->state == I801_TIMEOUT_RECOVERY) + i801_timeout_recovery_poll(adap, entry, d); + else if (d->block && !d->full_block) { + if (d->state == I801_WAIT_INTR) + i801_block_poll_wait_intr(adap, entry, d); + else + i801_block_poll(adap, entry, d); + if (entry->result < 0) + /* Error, finish the transaction */ + i801_finish(adap, entry, d); + } else { + i801_transaction_poll(adap, entry, d); + if (entry->result < 0) + /* Error, finish the transaction */ + i801_finish(adap, entry, d); } - return result; } -/* Return negative errno 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) +/* Start a general SMBUS transaction on the i801. Figure out what + kind of transaction it is, set it up, and start it. */ +static int i801_start(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry) { - int hwpec; - int block = 0; - int ret, xact = 0; + struct i801_i2c_data *d = adap->algo_data; + int ret; + unsigned char host_addr; + + dev_dbg(&I801_dev->dev, "start call for %p %p at %ld\n", adap, entry, + jiffies); + + d->block = 0; + d->full_block = 0; + d->hwpec = 0; + d->xact = 0; + d->state = 0; + d->finished = 0; + + d->hwpec = (i801_features & FEATURE_SMBUS_PEC) + && (entry->smbus.flags & I2C_CLIENT_PEC) + && entry->smbus.size != I2C_SMBUS_QUICK + && entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA; - hwpec = (i801_features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) - && size != I2C_SMBUS_QUICK - && size != I2C_SMBUS_I2C_BLOCK_DATA; + entry->data = d; - switch (size) { + host_addr = (((entry->smbus.addr & 0x7f) << 1) + | (entry->smbus.read_write & 0x01)); + + switch (entry->smbus.size) { case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - xact = I801_QUICK; + outb_p(host_addr, SMBHSTADD); + d->xact = I801_QUICK; break; case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - xact = I801_BYTE; + outb_p(host_addr, SMBHSTADD); + if (entry->smbus.read_write == I2C_SMBUS_WRITE) + outb_p(entry->smbus.command, SMBHSTCMD); + d->xact = I801_BYTE; break; case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - xact = I801_BYTE_DATA; + outb_p(host_addr, 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; break; case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + outb_p(host_addr, 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); } - xact = I801_WORD_DATA; + d->xact = I801_WORD_DATA; break; case I2C_SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - block = 1; + outb_p(host_addr, SMBHSTADD); + outb_p(entry->smbus.command, SMBHSTCMD); + d->block = 1; break; case I2C_SMBUS_I2C_BLOCK_DATA: /* NB: page 240 of ICH5 datasheet shows that the R/#W * bit should be cleared here, even when reading */ - outb_p((addr & 0x7f) << 1, SMBHSTADD); - if (read_write == I2C_SMBUS_READ) { + outb_p((host_addr & 0x7f) << 1, SMBHSTADD); + if (entry->smbus.read_write == I2C_SMBUS_READ) { /* NB: page 240 of ICH5 datasheet also shows * that DATA1 is the cmd field when reading */ - outb_p(command, SMBHSTDAT1); + outb_p(entry->smbus.command, SMBHSTDAT1); } else - outb_p(command, SMBHSTCMD); - block = 1; + outb_p(entry->smbus.command, SMBHSTCMD); + d->block = 1; break; default: - dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; + dev_err(&I801_dev->dev, "Unsupported transaction %d\n", + entry->smbus.size); + return -EINVAL; } - if (hwpec) /* enable/disable hardware PEC */ + if (d->hwpec) /* enable/disable hardware PEC */ outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_CRC, SMBAUXCTL); else outb_p(inb_p(SMBAUXCTL) & (~SMBAUXCTL_CRC), SMBAUXCTL); - if(block) - ret = i801_block_transaction(data, read_write, size, hwpec); - else - ret = i801_transaction(xact | ENABLE_INT9); - - /* Some BIOSes don't like it when PEC is enabled at reboot or resume - time, so we forcibly disable it after every transaction. Turn off - E32B for the same reason. */ - if (hwpec || block) - outb_p(inb_p(SMBAUXCTL) & ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), - SMBAUXCTL); + if (d->block) { + ret = i801_block_start(adap, entry, d); + if (ret) + /* Error, finish the transaction */ + i801_finish(adap, entry, d); + } else { + d->xact |= ENABLE_INT9; + ret = i801_transaction_start(adap, entry, d); + if (ret) + /* Error, finish the transaction */ + i801_finish(adap, entry, d); + } - if(block) - return ret; - if(ret) - return ret; - if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) - return 0; + /* Wait extra long here, we want at least 2 ticks to guarantee + we wait >= 1 tick. But we want to wait at least 100us no + matter what. */ +#if ((1000000 / HZ) < 100) + entry->call_again_us = 200; +#else + entry->call_again_us = (1000000 / HZ) * 2; +#endif + entry->time_left = MAX_TIMEOUT_US; - 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; + return ret; } @@ -551,7 +694,8 @@ static u32 i801_func(struct i2c_adapter } static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = i801_access, + .smbus_start = i801_start, + .poll = i801_poll, .functionality = i801_func, }; @@ -559,6 +703,7 @@ static struct i2c_adapter i801_adapter = .owner = THIS_MODULE, .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, .algo = &smbus_algorithm, + .algo_data = &i801_data, }; static struct pci_device_id i801_ids[] = { Index: linux-2.6.30/drivers/i2c/busses/i2c-piix4.c =================================================================== --- linux-2.6.30.orig/drivers/i2c/busses/i2c-piix4.c +++ linux-2.6.30/drivers/i2c/busses/i2c-piix4.c @@ -67,7 +67,7 @@ #define SMBREV 0x0D6 /* Other settings */ -#define MAX_TIMEOUT 500 +#define MAX_TIMEOUT_US 500000 #define ENABLE_INT9 0 /* PIIX4 constants */ @@ -77,6 +77,8 @@ #define PIIX4_WORD_DATA 0x0C #define PIIX4_BLOCK_DATA 0x14 +#define RETRY_TIME_US 500 /* Try every 500us minimum */ + /* insmod parameters */ /* If force is set to anything different from 0, we forcibly enable the @@ -290,64 +292,45 @@ static int __devinit piix4_setup_sb800(s return 0; } -static int piix4_transaction(void) +static void piix4_poll(struct i2c_adapter *adap, + struct i2c_op_q_entry *e, + unsigned int us_since_last_poll) { int temp; - int result = 0; - int timeout = 0; - - dev_dbg(&piix4_adapter.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), - inb_p(SMBHSTDAT1)); + int i; - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { - dev_dbg(&piix4_adapter.dev, "SMBus busy (%02x). " - "Resetting...\n", temp); - outb_p(temp, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { - dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp); - return -EBUSY; + temp = inb_p(SMBHSTSTS); + if (temp & 0x01) { + e->time_left -= us_since_last_poll; + if (e->time_left <= 0) { + dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); + e->result = -EBUSY; + goto out_done; } else { - dev_dbg(&piix4_adapter.dev, "Successful!\n"); + /* Not done, return to restart the timer */ + e->call_again_us = RETRY_TIME_US; } - } - - /* start the transaction by setting bit 6 */ - outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); - - /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ - if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */ - msleep(2); - else - msleep(1); - - while ((timeout++ < MAX_TIMEOUT) && - ((temp = inb_p(SMBHSTSTS)) & 0x01)) - msleep(1); - - /* If the SMBus is still busy, we give up */ - if (timeout >= MAX_TIMEOUT) { - dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); - result = -ETIMEDOUT; + return; } if (temp & 0x10) { - result = -EIO; + e->result = -EIO; dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n"); + goto out_done; } if (temp & 0x08) { - result = -EIO; + e->result = -EIO; dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be " "locked until next hard reset. (sorry!)\n"); /* Clock stops and slave is stuck in mid-transmission */ + goto out_done; } if (temp & 0x04) { - result = -ENXIO; + e->result = -ENODEV; dev_dbg(&piix4_adapter.dev, "Error: no response!\n"); + goto out_done; } if (inb_p(SMBHSTSTS) != 0x00) @@ -361,95 +344,127 @@ static int piix4_transaction(void) "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); - return result; + + if ((e->smbus.read_write == I2C_SMBUS_WRITE) + || (e->smbus.size == PIIX4_QUICK)) + goto out_done; + + switch (e->smbus.size) { + case PIIX4_BYTE: + case PIIX4_BYTE_DATA: + e->smbus.data->byte = inb_p(SMBHSTDAT0); + break; + case PIIX4_WORD_DATA: + e->smbus.data->word = (inb_p(SMBHSTDAT0) + + (inb_p(SMBHSTDAT1) << 8)); + break; + case PIIX4_BLOCK_DATA: + e->smbus.data->block[0] = inb_p(SMBHSTDAT0); + if (e->smbus.data->block[0] == 0 || + e->smbus.data->block[0] > I2C_SMBUS_BLOCK_MAX) { + e->result = -EPROTO; + goto out_done; + } + i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ + for (i = 1; i <= e->smbus.data->block[0]; i++) + e->smbus.data->block[i] = inb_p(SMBBLKDAT); + break; + } + + out_done: + i2c_op_done(adap, e); } /* Return negative errno on error. */ -static s32 piix4_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) +static int piix4_smbus_start(struct i2c_adapter *adap, + struct i2c_op_q_entry *e) { int i, len; - int status; + int temp; - switch (size) { + switch (e->smbus.size) { case I2C_SMBUS_QUICK: - outb_p((addr << 1) | read_write, - SMBHSTADD); - size = PIIX4_QUICK; + outb_p((e->smbus.addr << 1) | e->smbus.read_write, SMBHSTADD); + e->smbus.size = PIIX4_QUICK; break; case I2C_SMBUS_BYTE: - outb_p((addr << 1) | read_write, - SMBHSTADD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - size = PIIX4_BYTE; + outb_p((e->smbus.addr << 1) | e->smbus.read_write, SMBHSTADD); + if (e->smbus.read_write == I2C_SMBUS_WRITE) + outb_p(e->smbus.command, SMBHSTCMD); + e->smbus.size = PIIX4_BYTE; break; case I2C_SMBUS_BYTE_DATA: - outb_p((addr << 1) | read_write, - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - size = PIIX4_BYTE_DATA; + outb_p((e->smbus.addr << 1) | e->smbus.read_write, SMBHSTADD); + outb_p(e->smbus.command, SMBHSTCMD); + if (e->smbus.read_write == I2C_SMBUS_WRITE) + outb_p(e->smbus.data->byte, SMBHSTDAT0); + e->smbus.size = PIIX4_BYTE_DATA; break; case I2C_SMBUS_WORD_DATA: - outb_p((addr << 1) | read_write, - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); + outb_p((e->smbus.addr << 1) | e->smbus.read_write, SMBHSTADD); + outb_p(e->smbus.command, SMBHSTCMD); + if (e->smbus.read_write == I2C_SMBUS_WRITE) { + outb_p(e->smbus.data->word & 0xff, SMBHSTDAT0); + outb_p((e->smbus.data->word & 0xff00) >> 8, + SMBHSTDAT1); } - size = PIIX4_WORD_DATA; + e->smbus.size = PIIX4_WORD_DATA; break; case I2C_SMBUS_BLOCK_DATA: - outb_p((addr << 1) | read_write, - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; + outb_p((e->smbus.addr << 1) | e->smbus.read_write, SMBHSTADD); + outb_p(e->smbus.command, SMBHSTCMD); + if (e->smbus.read_write == I2C_SMBUS_WRITE) { + len = e->smbus.data->block[0]; if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) return -EINVAL; outb_p(len, SMBHSTDAT0); i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ for (i = 1; i <= len; i++) - outb_p(data->block[i], SMBBLKDAT); + outb_p(e->smbus.data->block[i], SMBBLKDAT); } - size = PIIX4_BLOCK_DATA; + e->smbus.size = PIIX4_BLOCK_DATA; break; default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); + dev_warn(&adap->dev, "Unsupported transaction %d\n", + e->smbus.size); return -EOPNOTSUPP; } - outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); + outb_p((e->smbus.size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); - status = piix4_transaction(); - if (status) - return status; + dev_dbg(&piix4_adapter.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), + inb_p(SMBHSTDAT1)); - if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK)) - return 0; + /* Make sure the SMBus host is ready to start transmitting */ + temp = inb_p(SMBHSTSTS); + if (temp != 0x00) { + dev_dbg(&piix4_adapter.dev, "SMBus busy (%02x). " + "Resetting...\n", temp); + outb_p(temp, SMBHSTSTS); + temp = inb_p(SMBHSTSTS); + if (temp != 0x00) { + dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp); + return -EBUSY; + } else { + dev_dbg(&piix4_adapter.dev, "Successfull!\n"); + } + } + /* start the transaction by setting bit 6 */ + outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); + + /* We will always wait for a fraction of a second! (See PIIX4 + docs errata), at least 1 jiffie (force 2 jiffies since we + might be at the end of a jiffie). So we don't check if it + is done now. */ + if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */ + e->call_again_us = 3 * (1000000 / HZ); + else + e->call_again_us = 2 * (1000000 / HZ); + e->time_left = MAX_TIMEOUT_US; - switch (size) { - case PIIX4_BYTE: - case PIIX4_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case PIIX4_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case PIIX4_BLOCK_DATA: - data->block[0] = inb_p(SMBHSTDAT0); - if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMBBLKDAT); - break; - } return 0; } @@ -461,7 +476,8 @@ static u32 piix4_func(struct i2c_adapter } static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = piix4_access, + .smbus_start = piix4_smbus_start, + .poll = piix4_poll, .functionality = piix4_func, }; Index: linux-2.6.30/drivers/i2c/i2c-core.c =================================================================== --- linux-2.6.30.orig/drivers/i2c/i2c-core.c +++ linux-2.6.30/drivers/i2c/i2c-core.c @@ -38,6 +38,7 @@ #include "i2c-core.h" +#define USEC_PER_JIFFIE (1000000 / HZ) static DEFINE_MUTEX(core_lock); static DEFINE_IDR(i2c_adapter_idr); @@ -447,7 +448,21 @@ static int i2c_register_adapter(struct i mutex_init(&adap->bus_lock); mutex_init(&adap->clist_lock); + spin_lock_init(&adap->q_lock); + INIT_LIST_HEAD(&adap->q); 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; mutex_lock(&core_lock); @@ -658,6 +673,13 @@ int i2c_del_adapter(struct i2c_adapter * } } + /* Stop the timer and free its memory. */ + adap->timer->deleted = 1; + /* Timer can no longer be started now. */ + del_timer_sync(&adap->timer->timer); + kfree(adap->timer); + adap->timer = NULL; + /* clean up the sysfs representation */ init_completion(&adap->dev_released); device_unregister(&adap->dev); @@ -1004,26 +1026,176 @@ postcore_initcall(i2c_init); module_exit(i2c_exit); /* ---------------------------------------------------- - * the functional interface to the i2c busses. + * Timer operations * ---------------------------------------------------- */ +static void i2c_handle_timer(unsigned long data); -/** - * i2c_transfer - execute a single or combined I2C message - * @adap: Handle to I2C bus - * @msgs: One or more messages to execute before STOP is issued to - * terminate the operation; each message begins with a START. - * @num: Number of messages to be executed. - * - * Returns negative errno, else the number of messages executed. - * - * Note that there is no requirement that each message be sent to - * the same slave address, although that is the most common model. +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->deleted && !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); + } + spin_unlock_irqrestore(&t->lock, flags); +} + +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; + + spin_lock_irqsave(&t->lock, flags); + adap = t->adapter; + t->running = 0; + spin_unlock_irqrestore(&t->lock, flags); + + entry = i2c_entry_get(adap); + pr_debug("i2c_handle_timer: %p %p\n", adap, entry); + if (entry) { + adap->algo->poll(adap, entry, t->next_call_time); + + spin_lock_irqsave(&adap->q_lock, flags); + if (entry->use_timer) + i2c_start_timer(adap, entry); + spin_unlock_irqrestore(&adap->q_lock, flags); + i2c_entry_put(adap, entry); + } +} + +/* ---------------------------------------------------- + * the functional interface to the i2c busses. + * ---------------------------------------------------- */ -int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) + +/* Must be called with the q_lock held. */ +static int i2c_start_entry(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry) { int ret; + entry->state = I2C_OP_INITIALIZED; + switch (entry->xfer_type) { + case I2C_OP_I2C: + ret = adap->algo->master_start(adap, entry); + break; + case I2C_OP_SMBUS: + ret = adap->algo->smbus_start(adap, entry); + break; + default: + ret = -EINVAL; + } + + if (!ret && entry->use_timer) + i2c_start_timer(adap, entry); + + return ret; +} + +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_init_entry(struct i2c_op_q_entry *entry) +{ + entry->start = NULL; + entry->state = I2C_OP_QUEUED; + entry->result = 0; + entry->data = NULL; + kref_init(&entry->usecount); +} + +static void i2c_perform_op_wait(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry) +{ + struct completion done; + unsigned long flags; + const struct i2c_algorithm *algo = adap->algo; + int ret = 0; + + pr_debug("i2c_perform_op_wait %p %p\n", adap, entry); + i2c_init_entry(entry); + entry->use_timer = 0; /* We poll it directly. */ + init_completion(&done); + entry->handler = i2c_wait_complete; + entry->handler_data = &done; + + 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 */ + ret = i2c_start_entry(adap, entry); + if (ret) { + entry->result = ret; + list_del(&entry->link); + } + spin_unlock_irqrestore(&adap->q_lock, flags); + } 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->state == I2C_OP_QUEUED) { + /* + * Wait was interrupted before the entry was + * started. + */ + entry->result = -ERESTARTSYS; + list_del(&entry->link); + } + spin_unlock_irqrestore(&adap->q_lock, flags); + } + + /* + * Once the operation is started, we will not + * interrupt it. + */ + while (entry->state != I2C_OP_FINISHED) { + 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->state == I2C_OP_FINISHED) + break; + algo->poll(adap, entry, timeout * USEC_PER_JIFFIE); + } +} + +static void i2c_transfer_entry(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry) +{ +#ifdef DEBUG + int ret; +#endif /* REVISIT the fault reporting model here is weak: * * - When we get an error after receiving N bytes from a slave, @@ -1041,34 +1213,71 @@ int i2c_transfer(struct i2c_adapter *ada * (discarding status on the first one). */ - if (adap->algo->master_xfer) { + entry->xfer_type = I2C_OP_I2C; #ifdef DEBUG - for (ret = 0; ret < num; ret++) { - dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " - "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD) - ? 'R' : 'W', msgs[ret].addr, msgs[ret].len, - (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); - } + for (ret = 0; ret < entry->i2c.num; ret++) { + dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " + "len=%d%s\n", ret, + (entry->i2c.msgs[ret].flags & I2C_M_RD ? + 'R' : 'W'), + entry->i2c.msgs[ret].addr, entry->i2c.msgs[ret].len, + (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); + } #endif - + if (adap->algo->master_start) + i2c_perform_op_wait(adap, entry); + else if (adap->algo->master_xfer) { if (in_atomic() || irqs_disabled()) { - ret = mutex_trylock(&adap->bus_lock); - if (!ret) + if (!mutex_trylock(&adap->bus_lock)) { /* I2C activity is ongoing. */ - return -EAGAIN; + entry->result = -EAGAIN; + return; + } } else { mutex_lock_nested(&adap->bus_lock, adap->level); } - ret = adap->algo->master_xfer(adap,msgs,num); + entry->result = adap->algo->master_xfer(adap, entry->i2c.msgs, + entry->i2c.num); mutex_unlock(&adap->bus_lock); - - return ret; + if (entry->complete) + entry->complete(adap, entry); } else { dev_dbg(&adap->dev, "I2C level transfers not supported\n"); - return -EOPNOTSUPP; + entry->result = -EOPNOTSUPP; } } + +/** + * i2c_transfer - execute a single or combined I2C message + * @adap: Handle to I2C bus + * @msgs: One or more messages to execute before STOP is issued to + * terminate the operation; each message begins with a START. + * @num: Number of messages to be executed. + * + * Returns negative errno, else the number of messages executed. + * + * Note that there is no requirement that each message be sent to + * the same slave address, although that is the most common model. + */ +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; + entry->complete = NULL; + + i2c_transfer_entry(adap, entry); + rv = entry->result; + kfree(entry); + return rv; +} EXPORT_SYMBOL(i2c_transfer); /** @@ -1812,169 +2021,195 @@ s32 i2c_smbus_write_i2c_block_data(struc } EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); -/* 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[I2C_SMBUS_BLOCK_MAX+3]; - unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; - 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 } - }; +static void i2c_smbus_emu_complete(struct i2c_adapter *adapter, + struct i2c_op_q_entry *entry) +{ + unsigned char *msgbuf0 = entry->i2c.msgs[0].buf; + unsigned char *msgbuf1 = entry->i2c.msgs[1].buf; + int num = entry->smbus.read_write == I2C_SMBUS_READ ? 2 : 1; int i; - u8 partial_pec = 0; int status; - msgbuf0[0] = command; - switch(size) { + if (entry->result < 0) + return; + + 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: + for (i = 0; i < entry->smbus.data->block[0]; i++) + entry->smbus.data->block[i + 1] = msgbuf1[i]; + break; + case I2C_SMBUS_BLOCK_DATA: + case I2C_SMBUS_BLOCK_PROC_CALL: + for (i = 0; i < msgbuf1[0] + 1; i++) + entry->smbus.data->block[i] = msgbuf1[i]; + break; + } + + /* Check PEC if last message is a read */ + if (entry->pec && (entry->i2c.msgs[num - 1].flags & I2C_M_RD)) { + status = i2c_smbus_check_pec(entry->partial_pec, + &entry->i2c.msgs[num - 1]); + if (status < 0) + entry->result = status; + } +} + +static int i2c_smbus_emu_format(struct i2c_adapter *adapter, + 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; + int num = entry->smbus.read_write == I2C_SMBUS_READ ? 2 : 1; + struct i2c_msg *msg = entry->msg; + int i; + + entry->i2c.msgs = msg; + entry->i2c.msgs[0].buf = msgbuf0; + entry->i2c.msgs[1].buf = entry->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 = 0; + + msgbuf0[0] = entry->smbus.command; + switch (entry->smbus.size) { case I2C_SMBUS_QUICK: msg[0].len = 0; /* Special case: The read/write field is used as data */ - msg[0].flags = flags | (read_write == I2C_SMBUS_READ ? - I2C_M_RD : 0); + msg[0].flags = (entry->smbus.flags | + ((entry->smbus.read_write == I2C_SMBUS_READ) + ? I2C_M_RD : 0)); num = 1; break; case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_READ) { + if (entry->smbus.read_write == I2C_SMBUS_READ) { /* Special case: only a read! */ - msg[0].flags = I2C_M_RD | flags; + msg[0].flags = I2C_M_RD | entry->smbus.flags; num = 1; } break; case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_READ) + if (entry->smbus.read_write == I2C_SMBUS_READ) msg[1].len = 1; else { msg[0].len = 2; - msgbuf0[1] = data->byte; + msgbuf0[1] = entry->smbus.data->byte; } break; case I2C_SMBUS_WORD_DATA: - if (read_write == I2C_SMBUS_READ) + if (entry->smbus.read_write == I2C_SMBUS_READ) msg[1].len = 2; else { - msg[0].len=3; - msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = data->word >> 8; + msg[0].len = 3; + msgbuf0[1] = entry->smbus.data->word & 0xff; + msgbuf0[2] = entry->smbus.data->word >> 8; } break; case I2C_SMBUS_PROC_CALL: num = 2; /* Special case */ - read_write = I2C_SMBUS_READ; + entry->smbus.read_write = I2C_SMBUS_READ; msg[0].len = 3; msg[1].len = 2; - msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = data->word >> 8; + msgbuf0[1] = entry->smbus.data->word & 0xff; + msgbuf0[2] = entry->smbus.data->word >> 8; break; case I2C_SMBUS_BLOCK_DATA: - if (read_write == I2C_SMBUS_READ) { + if (entry->smbus.read_write == I2C_SMBUS_READ) { msg[1].flags |= I2C_M_RECV_LEN; msg[1].len = 1; /* block length will be added by the underlying bus driver */ } else { - msg[0].len = data->block[0] + 2; + msg[0].len = entry->smbus.data->block[0] + 2; if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { dev_err(&adapter->dev, "Invalid block write size %d\n", - data->block[0]); + entry->smbus.data->block[0]); return -EINVAL; } for (i = 1; i < msg[0].len; i++) - msgbuf0[i] = data->block[i-1]; + msgbuf0[i] = entry->smbus.data->block[i - 1]; } break; case I2C_SMBUS_BLOCK_PROC_CALL: num = 2; /* Another special case */ - read_write = I2C_SMBUS_READ; - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { + entry->smbus.read_write = I2C_SMBUS_READ; + if (entry->smbus.data->block[0] > I2C_SMBUS_BLOCK_MAX) { dev_err(&adapter->dev, "Invalid block write size %d\n", - data->block[0]); + entry->smbus.data->block[0]); return -EINVAL; } - msg[0].len = data->block[0] + 2; + msg[0].len = entry->smbus.data->block[0] + 2; for (i = 1; i < msg[0].len; i++) - msgbuf0[i] = data->block[i-1]; + msgbuf0[i] = entry->smbus.data->block[i-1]; msg[1].flags |= I2C_M_RECV_LEN; msg[1].len = 1; /* block length will be added by the underlying bus driver */ break; case I2C_SMBUS_I2C_BLOCK_DATA: - if (read_write == I2C_SMBUS_READ) { - msg[1].len = data->block[0]; + if (entry->smbus.read_write == I2C_SMBUS_READ) { + msg[1].len = entry->smbus.data->block[0]; } else { - msg[0].len = data->block[0] + 1; + msg[0].len = entry->smbus.data->block[0] + 1; if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { dev_err(&adapter->dev, "Invalid block write size %d\n", - data->block[0]); + entry->smbus.data->block[0]); return -EINVAL; } - for (i = 1; i <= data->block[0]; i++) - msgbuf0[i] = data->block[i]; + for (i = 1; i <= entry->smbus.data->block[0]; i++) + msgbuf0[i] = entry->smbus.data->block[i]; } break; default: - dev_err(&adapter->dev, "Unsupported transaction %d\n", size); + dev_err(&adapter->dev, "Unsupported transaction %d\n", + entry->smbus.size); return -EOPNOTSUPP; } - i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK - && size != I2C_SMBUS_I2C_BLOCK_DATA); - if (i) { + entry->pec = ((entry->smbus.flags & I2C_CLIENT_PEC) + && entry->smbus.size != I2C_SMBUS_QUICK + && entry->smbus.size != I2C_SMBUS_I2C_BLOCK_DATA); + if (entry->pec) { /* Compute PEC if first message is a write */ if (!(msg[0].flags & I2C_M_RD)) { if (num == 1) /* Write only */ i2c_smbus_add_pec(&msg[0]); else /* Write followed by read */ - partial_pec = i2c_smbus_msg_pec(0, &msg[0]); + entry->partial_pec + = i2c_smbus_msg_pec(0, &msg[0]); } /* Ask for PEC if last message is a read */ - if (msg[num-1].flags & I2C_M_RD) - msg[num-1].len++; + if (msg[num - 1].flags & I2C_M_RD) + msg[num - 1].len++; } - status = i2c_transfer(adapter, msg, num); - if (status < 0) - return status; + entry->xfer_type = I2C_OP_I2C; + entry->i2c.msgs = msg; + entry->i2c.num = num; + entry->complete = i2c_smbus_emu_complete; - /* Check PEC if last message is a read */ - if (i && (msg[num-1].flags & I2C_M_RD)) { - status = i2c_smbus_check_pec(partial_pec, &msg[num-1]); - if (status < 0) - return status; - } - - 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: - for (i = 0; i < data->block[0]; i++) - data->block[i+1] = msgbuf1[i]; - break; - case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_BLOCK_PROC_CALL: - for (i = 0; i < msgbuf1[0] + 1; i++) - data->block[i] = msgbuf1[i]; - break; - } return 0; } @@ -1995,23 +2230,224 @@ s32 i2c_smbus_xfer(struct i2c_adapter *a char read_write, u8 command, int protocol, union i2c_smbus_data *data) { + struct i2c_op_q_entry *entry; s32 res; + const struct i2c_algorithm *algo = adapter->algo; - flags &= I2C_M_TEN | I2C_CLIENT_PEC; + entry = kmalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; - if (adapter->algo->smbus_xfer) { + 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 = protocol; + entry->smbus.data = data; + entry->complete = NULL; + + if (algo->smbus_start) { + i2c_perform_op_wait(adapter, entry); + } else if (algo->smbus_xfer) { mutex_lock(&adapter->bus_lock); - res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write, - command, protocol, data); + entry->result = adapter->algo->smbus_xfer + (adapter, entry->smbus.addr, entry->smbus.flags, + entry->smbus.read_write, entry->smbus.command, + entry->smbus.size, entry->smbus.data); mutex_unlock(&adapter->bus_lock); - } else - res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write, - command, protocol, data); + if (entry->complete) + entry->complete(adapter, entry); + } else { + if (i2c_smbus_emu_format(adapter, entry)) + entry->result = -EINVAL; + else { + i2c_transfer_entry(adapter, entry); + /* + * We get these back with the result being the + * number of bytes transferred. We want zero for + * success for this routine. + */ + if (entry->result > 0) + entry->result = 0; + } + } + res = entry->result; + kfree(entry); + if (res > 0) + res = 0; /* Always return 0 on success */ return res; } EXPORT_SYMBOL(i2c_smbus_xfer); +/* ---------------------------------------------------- + * Entry handling + * ---------------------------------------------------- + */ + +/* + * 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); + } + 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); + if (entry) { + if (entry->state != I2C_OP_INITIALIZED) + entry = NULL; + else + kref_get(&entry->usecount); + } + spin_unlock_irqrestore(&adap->q_lock, flags); + return entry; +} + +static void i2c_op_release(struct kref *ref) +{ + /* + * Nothing to do here, all handling is from the kref_put + * return code. + */ +} + +static void _i2c_entry_put(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry, + unsigned long *flags) +{ + while (kref_put(&entry->usecount, i2c_op_release)) { + list_del(&entry->link); + spin_unlock_irqrestore(&adap->q_lock, *flags); + + if (entry->complete) + entry->complete(adap, entry); + + entry->handler(entry); + + spin_lock_irqsave(&adap->q_lock, *flags); + entry = _i2c_entry_get(adap); + if (!entry) + break; + if (entry->state != I2C_OP_QUEUED) + /* Something else already started it. */ + break; + + entry->result = i2c_start_entry(adap, entry); + if (entry->start) + complete(entry->start); + if (!entry->result) + /* Successful start, we are done here. */ + break; + + /* + * If we get here, the start failed and we need to + * finish the entry. We haven't incremented the + * refcount, so looping again will cause it to be + * completed. + */ + } +} + +void i2c_entry_put(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry) +{ + unsigned long flags; + + pr_debug("i2c_put %p %p\n", adap, entry); + + spin_lock_irqsave(&adap->q_lock, flags); + _i2c_entry_put(adap, entry, &flags); + spin_unlock_irqrestore(&adap->q_lock, flags); +} +EXPORT_SYMBOL(i2c_entry_put); + +void i2c_op_done(struct i2c_adapter *adap, struct i2c_op_q_entry *entry) +{ + unsigned long flags; + + pr_debug("i2c_op_done: %p %p\n", adap, entry); + spin_lock_irqsave(&adap->q_lock, flags); + /* + * Guard against multiple calls to "done" for an entry. This + * can happen, for instance, if a timer poll and an interrupt + * both discover that the operation is finished and both + * report it. + */ + if (entry->state != I2C_OP_FINISHED) { + entry->state = I2C_OP_FINISHED; + _i2c_entry_put(adap, entry, &flags); + } + spin_unlock_irqrestore(&adap->q_lock, flags); +} +EXPORT_SYMBOL(i2c_op_done); + +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); +} +EXPORT_SYMBOL(i2c_poll); + +int i2c_non_blocking_op(struct i2c_client *client, + struct i2c_op_q_entry *entry) +{ + unsigned long flags; + struct i2c_adapter *adap = client->adapter; + int ret = 0; + + if (!i2c_non_blocking_capable(adap)) + return -ENOSYS; + + entry->smbus.addr = client->addr; + entry->smbus.flags = client->flags; + + if (entry->xfer_type == I2C_OP_SMBUS) { + if (!adap->algo->smbus_start) { + if (i2c_smbus_emu_format(adap, entry)) + return -EINVAL; + } + } + + i2c_init_entry(entry); + entry->use_timer = 1; /* Let the timer code poll it. */ + + 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 */ + ret = i2c_start_entry(adap, entry); + if (ret) + list_del(&entry->link); + } + spin_unlock_irqrestore(&adap->q_lock, flags); + return ret; +} +EXPORT_SYMBOL(i2c_non_blocking_op); + MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C-Bus main module"); MODULE_LICENSE("GPL"); Index: linux-2.6.30/include/linux/i2c.h =================================================================== --- linux-2.6.30.orig/include/linux/i2c.h +++ linux-2.6.30/include/linux/i2c.h @@ -34,6 +34,11 @@ #include /* for struct device */ #include /* for completion */ #include +#include +#include +#include +#include +#include extern struct bus_type i2c_bus_type; @@ -46,6 +51,7 @@ struct i2c_client; struct i2c_driver; union i2c_smbus_data; struct i2c_board_info; +struct i2c_op_q_entry; /* * The master routines are the ones normally used to transmit data to devices @@ -94,6 +100,24 @@ extern s32 i2c_smbus_write_i2c_block_dat u8 command, u8 length, const 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. + */ +extern int i2c_non_blocking_op(struct i2c_client *client, + struct i2c_op_q_entry *entry); + +/* + * 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); + + /** * struct i2c_driver - represent an I2C device driver * @id: Unique driver ID (optional) @@ -319,6 +343,37 @@ i2c_register_board_info(int busnum, stru #endif /* + * 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 @@ -337,11 +392,54 @@ struct i2c_algorithm { 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. 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, these + * should return an error. They are called with the queue lock + * held, so they should not call i2c_op_done(). + */ + int (*master_start)(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry); + int (*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); + /* To determine what the adapter supports */ u32 (*functionality) (struct i2c_adapter *); }; /* + * 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; + char deleted; + char running; + struct timer_list timer; + unsigned int next_call_time; + struct i2c_adapter *adapter; +}; + +/* * i2c_adapter is the structure used to identify a physical i2c bus along * with the access algorithms necessary to access it. */ @@ -361,6 +459,14 @@ struct i2c_adapter { struct mutex bus_lock; struct mutex clist_lock; + struct list_head q; + spinlock_t q_lock; + + /* + * Used to time non-blocking operations. + */ + struct i2c_timer *timer; + int timeout; /* in jiffies */ int retries; struct device dev; /* the adapter device */ @@ -471,6 +577,11 @@ static inline int i2c_adapter_id(struct { return adap->nr; } + +static inline int i2c_non_blocking_capable(struct i2c_adapter *adap) +{ + return adap->algo->poll != NULL; +} #endif /* __KERNEL__ */ /** @@ -593,6 +704,117 @@ union i2c_smbus_data { #ifdef __KERNEL__ +/* + * Hold an I2C operation to perform, and used to pass data around. + */ +#define I2C_OP_I2C 0 +#define I2C_OP_SMBUS 1 +typedef void (*i2c_op_done_cb)(struct i2c_op_q_entry *entry); +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). + */ + + /* + * Set to I2C_OP_I2C or I2C_OP_SMBUS depending on the transfer type. + */ + int xfer_type; + + /* + * Handler may be called from interrupt context, so be + * careful. + */ + i2c_op_done_cb handler; + void *handler_data; + + /* + * Set up the i2c or smbus structure, depending on the transfer + * type. + * + * Note that i2c and smbus are not in 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 changed + * 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; + + /**************************************************************/ + /* Bus Interface */ + /* + * The bus interface must set call_again_us to the time in + * microseconds until the next poll operation should be + * called. This *must* be set in the start operation + * function. The value may be changed in poll calls if the + * bus interface needs different timeouts at different times. + * The time_left and data can be used for anything the bus + * interface likes. data will be set to NULL before being + * started; the bus interface must use that to tell if the + * entry has been set up. It should ignore poll operations on + * entries that are not yet set up. + */ + unsigned int call_again_us; + long time_left; + void *data; + + /**************************************************************/ + /* Internals */ + struct completion *start; + unsigned char use_timer; +#define I2C_OP_QUEUED 0 +#define I2C_OP_INITIALIZED 1 +#define I2C_OP_FINISHED 2 + unsigned char state; + u8 pec; + u8 partial_pec; + void (*complete)(struct i2c_adapter *adap, + struct i2c_op_q_entry *entry); + + struct list_head link; + struct kref 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[I2C_SMBUS_BLOCK_MAX + 3]; + unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2]; + struct i2c_msg msg[2]; +}; + /* These defines are used for probing i2c client addresses */ /* The length of the option lists */ #define I2C_CLIENT_MAX_OPTS 48