diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2018-10-01 17:48:38 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-10-10 17:07:57 -0700 |
commit | 83af9ed091c8a10bae1fca0434d30ab66a3a07ab (patch) | |
tree | c728c0be1854cd95e2739fa53356a645ffe06c74 | |
parent | a02f8f2fe817f79182024b7aa847dbb0c32dbfc5 (diff) | |
download | chrome-ec-83af9ed091c8a10bae1fca0434d30ab66a3a07ab.tar.gz |
usb_i2c: extend protocol to allow longer writes
It is necessary to be able to send longer than 255 byte packets over
the USB I2C bridge.
This patch introduces a backwards compatible protocol extension to the
to allow that. Namely, the top 4 bits of the byte previously used as
the port number are now used as the top 4 bits of the 12 bit write
counter field.
BRANCH=cr50, cr50-mp
BUG=b:75976718
TEST=tested along with patches modifying Cr50 and iteflash for
operating over CCD. Verified that the ITE EC programming
requiring 256 byte write transactions succeeds.
Change-Id: I21475c8d87a6a858ff9ad96dae87388604bbbf2d
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1256059
Reviewed-by: Matthew Blecker <matthewb@chromium.org>
-rw-r--r-- | common/usb_i2c.c | 60 | ||||
-rw-r--r-- | include/usb_i2c.h | 30 |
2 files changed, 61 insertions, 29 deletions
diff --git a/common/usb_i2c.c b/common/usb_i2c.c index 3f0ac3c44c..241e86b5ce 100644 --- a/common/usb_i2c.c +++ b/common/usb_i2c.c @@ -45,7 +45,12 @@ static int16_t usb_i2c_map_error(int error) } } -static uint8_t usb_i2c_read_packet(struct usb_i2c_config const *config) +/* + * Return value should be large enough to accommodate the entire read queue + * buffer size. Let's use 4 bytes in case future designs have a lot of RAM and + * allow for large buffers. + */ +static uint32_t usb_i2c_read_packet(struct usb_i2c_config const *config) { return QUEUE_REMOVE_UNITS(config->consumer.queue, config->buffer, queue_count(config->consumer.queue)); @@ -59,35 +64,54 @@ static void usb_i2c_write_packet(struct usb_i2c_config const *config, static uint8_t usb_i2c_executable(struct usb_i2c_config const *config) { - /* - * In order to support larger write payload, we need to peek - * the queue to see if we need to wait for more data. - */ + static size_t expected_size; - uint8_t write_count; + if (!expected_size) { + uint8_t peek[4]; - if (queue_peek_units(config->consumer.queue, &write_count, 2, 1) == 1 - && (write_count + 4) > queue_count(config->consumer.queue)) { /* - * Feed me more data, please. - * Reuse the buffer in usb_i2c_config to send ACK packet. + * In order to support larger write payload, we need to peek + * the queue to see if we need to wait for more data. + */ + if (queue_peek_units(config->consumer.queue, + peek, 0, sizeof(peek)) + != sizeof(peek)) { + /* Not enough data to calculate expected_size. */ + return 0; + } + /* + * The first four bytes of the packet will describe its + * expected size. */ - config->buffer[0] = USB_I2C_SUCCESS; - config->buffer[1] = 0; - usb_i2c_write_packet(config, 4); - return 0; + /* Header bytes and extra rc bytes, if present. */ + if (peek[3] & 0x80) + expected_size = 6; + else + expected_size = 4; + + /* write count */ + expected_size += (((size_t)peek[0] & 0xf0) << 4) | peek[2]; } - return 1; + + + if (queue_count(config->consumer.queue) >= expected_size) { + expected_size = 0; + return 1; + } + + return 0; } static void usb_i2c_execute(struct usb_i2c_config const *config) { /* Payload is ready to execute. */ - uint8_t count = usb_i2c_read_packet(config); - int portindex = (config->buffer[0] >> 0) & 0xff; + uint32_t count = usb_i2c_read_packet(config); + int portindex = (config->buffer[0] >> 0) & 0xf; /* Convert 7-bit slave address to chromium EC 8-bit address. */ uint8_t slave_addr = (config->buffer[0] >> 7) & 0xfe; - int write_count = (config->buffer[1] >> 0) & 0xff; + + int write_count = ((config->buffer[0] << 4) & 0xf00) | + ((config->buffer[1] >> 0) & 0xff); int read_count = (config->buffer[1] >> 8) & 0xff; int offset = 0; /* Offset for extended reading header. */ diff --git a/include/usb_i2c.h b/include/usb_i2c.h index 939b26007a..b808de9e49 100644 --- a/include/usb_i2c.h +++ b/include/usb_i2c.h @@ -14,6 +14,11 @@ #define __CROS_USB_I2C_H /* + * This header file describes i2c encapsulation when communicated over USB. + * + * Note that current implementation assumes that there is only one instance of + * interface of this kind per device. + * * 2 forms of command are supported: * - When write payload + header is larger than 64 bytes, which exceed the * common USB packet (64 bytes), remaining payload should send without @@ -23,18 +28,18 @@ * be defined properly based on the use cases. * * - Read less than 128 (0x80) bytes. - * +------+------+----+----+---------------+ - * | port | addr | wc | rc | write payload | - * +------+------+----+----+---------------+ - * | 1B | 1B | 1B | 1B | < 256 bytes | - * +------+------+----+----+---------------+ + * +---------+------+----+----+---------------+ + * | wc/port | addr | wc | rc | write payload | + * +---------+------+----+----+---------------+ + * | 1B | 1B | 1B | 1B | < 256 bytes | + * +---------+------+----+----+---------------+ * * - Read less than 32768 (0x8000) bytes. - * +------+------+----+----+-----+----------+---------------+ - * | port | addr | wc | rc | rc1 | reserved | write payload | - * +------+------+----+----+----------------+---------------+ - * | 1B | 1B | 1B | 1B | 1B | 1B | < 256 bytes | - * +------+------+----+----+----------------+---------------+ + * +---------+------+----+----+-----+----------+---------------+ + * | wc/port | addr | wc | rc | rc1 | reserved | write payload | + * +---------+------+----+----+----------------+---------------+ + * | 1B | 1B | 1B | 1B | 1B | 1B | < 256 bytes | + * +---------+------+----+----+----------------+---------------+ * * - Special notes for rc and rc1: * If the most significant bit in rc is set (rc >= 0x80), this indicates @@ -43,7 +48,10 @@ * will be (rc1 << 7) | (rc & 0x7F). * * Fields: - * - port: port address, 1 byte, i2c interface index. + * + * - wc/port: 1 byte: 4 top bits are the 4 top bits of the 12 bit write + * counter, the 4 bottom bits are the port address, i2c interface + * index. * * - addr: slave address, 1 byte, i2c 7-bit bus address. * |