summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Bendebury <vbendeb@chromium.org>2018-10-01 17:48:38 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2019-04-02 21:09:14 +0000
commit74f2779c8a1ddc1d09458e01eca59e3527139f97 (patch)
tree6897905624bbc79d2911f660a502204749c66734
parentadd38b392e3d2f0e94629e91f77cf5ccd57a8418 (diff)
downloadchrome-ec-74f2779c8a1ddc1d09458e01eca59e3527139f97.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> (cherry picked from commit 83af9ed091c8a10bae1fca0434d30ab66a3a07ab) Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1549604 Commit-Queue: Ruben Rodriguez Buchillon <coconutruben@chromium.org> Tested-by: Ruben Rodriguez Buchillon <coconutruben@chromium.org> Reviewed-by: Nick Sanders <nsanders@chromium.org>
-rw-r--r--common/usb_i2c.c60
-rw-r--r--include/usb_i2c.h30
2 files changed, 61 insertions, 29 deletions
diff --git a/common/usb_i2c.c b/common/usb_i2c.c
index a92c411f1b..b1a81aa736 100644
--- a/common/usb_i2c.c
+++ b/common/usb_i2c.c
@@ -40,7 +40,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));
@@ -54,35 +59,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];
+ }
+
+
+ if (queue_count(config->consumer.queue) >= expected_size) {
+ expected_size = 0;
+ return 1;
}
- return 1;
+
+ return 0;
}
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 c135066e26..29b4fb4ef8 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.
*