diff --git a/README.rst b/README.rst index b393245..1b837b4 100644 --- a/README.rst +++ b/README.rst @@ -152,10 +152,6 @@ Caveats The ch341 doesn't work with a Wii nunchuk, possibly because the pull-up value is too low (1500 ohms). -i2c AT24 eeproms can be read but not programmed properly because the -at24 linux driver tries to write a byte at a time, and doesn't wait at -all (or enough) between writes. Data corruption on writes does occur. - The GPIOs --------- diff --git a/i2c-ch341.c b/i2c-ch341.c index fa2e520..bf3cb15 100644 --- a/i2c-ch341.c +++ b/i2c-ch341.c @@ -32,36 +32,21 @@ #define CH341_CMD_I2C_STM_IN 0xC0 #define CH341_CMD_I2C_STM_SET 0x60 -/* - * The maximum request size is 4096 bytes, both for reading and - * writing, split in up to 128 32-byte segments, which includes the - * CH341 commands and the I2C data. - */ -#define SEG_COUNT 128 - -/* - * Limit the transfer size that can be written. 4KiB is the maximum - * size of the whole buffer, but it must include all the command - * delimiters. 3KiB sounds reasonable. - */ -#define MAX_RW_LENGTH 3072 +/* Limit the transfer read size in one go to 32 bytes. */ +#define MAX_RD_LENGTH 32 struct ch341_i2c { struct i2c_adapter adapter; - - /* I2C request and response state */ - int idx_out; /* current offset in buf */ - int out_seg; /* current segment */ u8 *i2c_buf; }; /* - * Special case the no data transfer (SMBUS quick message), since some - * parameters are a bit different than the normal case. + * Check whether the device is busy. The CH341 sets a bit in the first + * byte if it cannot process a new command yet. */ -static int no_data_xfer(struct i2c_adapter *adapter, const struct i2c_msg *msg) +static int is_dev_busy(const struct i2c_adapter *adapter, const struct i2c_msg *msg) { - struct ch341_i2c *dev = i2c_get_adapdata(adapter); + const struct ch341_i2c *dev = i2c_get_adapdata(adapter); struct ch341_ddata *ddata = adapter->algo_data; u8 *out = dev->i2c_buf; int actual; @@ -70,242 +55,182 @@ static int no_data_xfer(struct i2c_adapter *adapter, const struct i2c_msg *msg) out[0] = CH341_CMD_I2C_STREAM; out[1] = CH341_CMD_I2C_STM_STA; out[2] = CH341_CMD_I2C_STM_OUT; - out[3] = msg->addr << 1 | (msg->flags & I2C_M_RD); - out[4] = CH341_CMD_I2C_STM_IN; - out[5] = CH341_CMD_I2C_STM_STO; - out[6] = CH341_CMD_I2C_STM_END; + out[3] = msg->addr << 1; + out[4] = CH341_CMD_I2C_STM_STO; + out[5] = CH341_CMD_I2C_STM_END; mutex_lock(&ddata->usb_lock); - /* Issue the request */ ret = usb_bulk_msg(ddata->usb_dev, usb_sndbulkpipe(ddata->usb_dev, ddata->ep_out), - dev->i2c_buf, 7, &actual, DEFAULT_TIMEOUT_MS); - if (ret < 0) { - mutex_unlock(&ddata->usb_lock); - return ret; - } - - ret = usb_bulk_msg(ddata->usb_dev, - usb_rcvbulkpipe(ddata->usb_dev, ddata->ep_in), - dev->i2c_buf, 2, &actual, - DEFAULT_TIMEOUT_MS); - if (ret < 0) { - mutex_unlock(&ddata->usb_lock); - return ret; + dev->i2c_buf, 6, &actual, DEFAULT_TIMEOUT_MS); + if (ret == 0) { + ret = usb_bulk_msg(ddata->usb_dev, + usb_rcvbulkpipe(ddata->usb_dev, ddata->ep_in), + dev->i2c_buf, SEG_SIZE, &actual, + DEFAULT_TIMEOUT_MS); } mutex_unlock(&ddata->usb_lock); - if (actual != 2 || dev->i2c_buf[0] & 0x80) - return -ETIMEDOUT; + if (ret == 0 && (actual != 1 || dev->i2c_buf[0] & 0x80)) + ret = -ETIMEDOUT; - return 1; + return ret; } -/* - * Append a write command to the current request. A set of 32-byte - * packets is filled. Each packet starts with STREAM and finishes with - * END, and contains an OUT field, leaving up to 29 bytes of data. The - * first packet must also include a START and the device address. - */ -static int append_write(struct ch341_i2c *dev, const struct i2c_msg *msg) +static int ch341_i2c_write(const struct i2c_adapter *adapter, const struct i2c_msg *msg) { + const struct ch341_i2c *dev = i2c_get_adapdata(adapter); + struct ch341_ddata *ddata = adapter->algo_data; + const u8 *src = msg->buf; bool start_done = false; - u8 *out = dev->i2c_buf; - int len; - u8 *p; - - len = msg->len; - p = msg->buf; - - while (len) { - int to_write; - int avail; - - if (dev->idx_out % SEG_SIZE) { - /* Finish current packet, and advance to the next one */ - out[dev->idx_out++] = CH341_CMD_I2C_STM_END; - dev->out_seg++; - dev->idx_out = dev->out_seg * SEG_SIZE; - - if (dev->out_seg == SEG_COUNT) - return -E2BIG; - } - - out[dev->idx_out++] = CH341_CMD_I2C_STREAM; + bool stop_done = false; + unsigned int len; + int actual; + int ret; - /* account for stream start and end */ - avail = SEG_SIZE - 3; + ret = is_dev_busy(adapter, msg); + if (ret) + return ret; - if (!start_done) { - /* Each message has a start */ - out[dev->idx_out++] = CH341_CMD_I2C_STM_STA; + len = msg->len; - avail -= 2; /* room for STA and device address */ - } + while (!stop_done) { + u8 *out = dev->i2c_buf; + unsigned int to_write; - to_write = min_t(int, len, avail); + *out++ = CH341_CMD_I2C_STREAM; - if (!start_done) { - out[dev->idx_out++] = CH341_CMD_I2C_STM_OUT | (to_write + 1); - out[dev->idx_out++] = msg->addr << 1; + if (start_done) { + to_write = min_t(unsigned int, len, SEG_SIZE - 3); + if (to_write) + *out++ = CH341_CMD_I2C_STM_OUT | to_write; + } else { + to_write = min_t(unsigned int, len, SEG_SIZE - 5); + *out++ = CH341_CMD_I2C_STM_STA; + *out++ = CH341_CMD_I2C_STM_OUT | (to_write + 1); + *out++ = msg->addr << 1; start_done = true; - } else { - out[dev->idx_out++] = CH341_CMD_I2C_STM_OUT | to_write; } - memcpy(&out[dev->idx_out], p, to_write); - dev->idx_out += to_write; + memcpy(out, src, to_write); + out += to_write; + src += to_write; len -= to_write; - p += to_write; - } - return 0; -} - -/* - * Append a read command to the request. It usually follows a write - * command. When that happens, the driver will attempt to concat the - * read command into the same packet. Each read command, of up to 32 - * bytes, must be written to a new packet. It is not possible to - * concat them. - */ -static int append_read(struct ch341_i2c *dev, const struct i2c_msg *msg) -{ - bool start_done = false; - u8 *out = dev->i2c_buf; - int len; + /* Corner case. There may not be enough room to add + * the i2c STOP in this packet. Add it to the next + * (empty) packet. + */ + if (len == 0 && ((out - dev->i2c_buf) < (SEG_SIZE - 1))) { + *out++ = CH341_CMD_I2C_STM_STO; + stop_done = true; + } - len = msg->len; + *out++ = CH341_CMD_I2C_STM_END; - while (len) { - int to_read; - - if (dev->idx_out % SEG_SIZE) { - if (!start_done && - (dev->idx_out % SEG_SIZE) < (SEG_SIZE - 7)) { - /* There's enough left for a read */ - } else { - /* Finish current packet, and advance to the next one */ - out[dev->idx_out++] = CH341_CMD_I2C_STM_END; - dev->out_seg++; - dev->idx_out = dev->out_seg * SEG_SIZE; - - if (dev->out_seg == SEG_COUNT) - return -E2BIG; - - out[dev->idx_out++] = CH341_CMD_I2C_STREAM; - } - } else { - out[dev->idx_out++] = CH341_CMD_I2C_STREAM; - } + mutex_lock(&ddata->usb_lock); - if (!start_done) { - /* Each message has a start */ - out[dev->idx_out++] = CH341_CMD_I2C_STM_STA; - out[dev->idx_out++] = CH341_CMD_I2C_STM_OUT | 1; - out[dev->idx_out++] = msg->addr << 1 | 1; + ret = usb_bulk_msg(ddata->usb_dev, + usb_sndbulkpipe(ddata->usb_dev, ddata->ep_out), + dev->i2c_buf, out - dev->i2c_buf, &actual, DEFAULT_TIMEOUT_MS); - start_done = true; - } + mutex_unlock(&ddata->usb_lock); - /* Apparently the last command must be an STM_IN to - * read the last byte. Without it, the adapter gets - * lost. - */ - to_read = min_t(int, len, 32); - len -= to_read; - if (len == 0) { - if (to_read > 1) - out[dev->idx_out++] = CH341_CMD_I2C_STM_IN | (to_read - 1); - out[dev->idx_out++] = CH341_CMD_I2C_STM_IN; - } else { - out[dev->idx_out++] = CH341_CMD_I2C_STM_IN | to_read; - } + if (ret < 0) + return ret; } return 0; } -static int ch341_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) +static int ch341_i2c_read(const struct i2c_adapter *adapter, const struct i2c_msg *msg) { struct ch341_i2c *dev = i2c_get_adapdata(adapter); struct ch341_ddata *ddata = adapter->algo_data; - u8 *out = dev->i2c_buf; + u8 *dst = msg->buf; + unsigned int len; int actual; int ret; - int i; - - /* Special case */ - if (num == 1 && msgs[0].len == 0) - return no_data_xfer(adapter, &msgs[0]); - - /* Prepare the request */ - dev->idx_out = 0; - dev->out_seg = 0; - - for (i = 0; i != num; i++) { - if (msgs[i].flags & I2C_M_RD) - ret = append_read(dev, &msgs[i]); - else - ret = append_write(dev, &msgs[i]); - - if (ret) - return ret; - } - - /* Finish the last packet */ - if (SEG_SIZE - (dev->idx_out % SEG_SIZE) < 2) { - out[dev->idx_out++] = CH341_CMD_I2C_STM_END; - dev->out_seg++; - if (dev->out_seg == SEG_COUNT) - return -E2BIG; + len = msg->len; - dev->idx_out = dev->out_seg * SEG_SIZE; + while (len) { + u8 *out = dev->i2c_buf; + unsigned int to_read; - out[dev->idx_out++] = CH341_CMD_I2C_STREAM; - } + to_read = min_t(unsigned int, len, SEG_SIZE - 1); - out[dev->idx_out++] = CH341_CMD_I2C_STM_STO; - out[dev->idx_out++] = CH341_CMD_I2C_STM_END; + mutex_lock(&ddata->usb_lock); - mutex_lock(&ddata->usb_lock); + *out++ = CH341_CMD_I2C_STREAM; + *out++ = CH341_CMD_I2C_STM_STA; + *out++ = CH341_CMD_I2C_STM_OUT; /* request status byte */ + *out++ = (msg->addr << 1) | 1; - /* Issue the request */ - ret = usb_bulk_msg(ddata->usb_dev, - usb_sndbulkpipe(ddata->usb_dev, ddata->ep_out), - dev->i2c_buf, dev->idx_out, &actual, DEFAULT_TIMEOUT_MS); - if (ret < 0) { - mutex_unlock(&ddata->usb_lock); - return ret; - } + /* The last command must be an STM_IN to read + * the last byte. Without it, the adapter gets + * lost. + */ + if (to_read > 1) + *out++ = CH341_CMD_I2C_STM_IN | (to_read - 1); + *out++ = CH341_CMD_I2C_STM_IN; - for (i = 0; i != num; i++) { - if (!(msgs[i].flags & I2C_M_RD)) - continue; + *out++ = CH341_CMD_I2C_STM_STO; + *out++ = CH341_CMD_I2C_STM_END; + /* Issue the request */ ret = usb_bulk_msg(ddata->usb_dev, - usb_rcvbulkpipe(ddata->usb_dev, ddata->ep_in), - dev->i2c_buf, msgs[i].len, &actual, - DEFAULT_TIMEOUT_MS); + usb_sndbulkpipe(ddata->usb_dev, ddata->ep_out), + dev->i2c_buf, out - dev->i2c_buf, &actual, DEFAULT_TIMEOUT_MS); + if (ret < 0) { + mutex_unlock(&ddata->usb_lock); + return ret; + } + ret = usb_bulk_msg(ddata->usb_dev, + usb_rcvbulkpipe(ddata->usb_dev, ddata->ep_in), + dev->i2c_buf, to_read + 1, &actual, + DEFAULT_TIMEOUT_MS); if (ret) { mutex_unlock(&ddata->usb_lock); return ret; } - if (actual != msgs[i].len) { + if (actual < 1 || dev->i2c_buf[0] & 0x80) { mutex_unlock(&ddata->usb_lock); - return -EIO; + return -ETIMEDOUT; } - memcpy(msgs[i].buf, dev->i2c_buf, actual); + memcpy(dst, &dev->i2c_buf[1], to_read); + + mutex_unlock(&ddata->usb_lock); + + len -= to_read; + dst += to_read; } - mutex_unlock(&ddata->usb_lock); + return 0; +} + +static int ch341_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) +{ + int ret; + int i; + + for (i = 0; i != num; i++) { + struct i2c_msg *msg = &msgs[i]; + + if (msg->flags & I2C_M_RD) + ret = ch341_i2c_read(adapter, msg); + else + ret = ch341_i2c_write(adapter, msg); + + if (ret) + return ret; + } return num; } @@ -321,8 +246,7 @@ static const struct i2c_algorithm ch341_i2c_algorithm = { }; static const struct i2c_adapter_quirks ch341_i2c_quirks = { - .max_read_len = MAX_RW_LENGTH, - .max_write_len = MAX_RW_LENGTH, + .max_read_len = MAX_RD_LENGTH, }; static int ch341_i2c_probe(struct platform_device *pdev) @@ -336,7 +260,7 @@ static int ch341_i2c_probe(struct platform_device *pdev) if (ch341_i2c == NULL) return -ENOMEM; - ch341_i2c->i2c_buf = devm_kzalloc(&pdev->dev, SEG_COUNT * SEG_SIZE, GFP_KERNEL); + ch341_i2c->i2c_buf = devm_kzalloc(&pdev->dev, SEG_SIZE, GFP_KERNEL); if (ch341_i2c->i2c_buf == NULL) return -ENOMEM;