diff options
-rw-r--r-- | board/hammer/board.h | 4 | ||||
-rw-r--r-- | common/usb_i2c.c | 38 | ||||
-rw-r--r-- | include/config.h | 3 | ||||
-rw-r--r-- | include/usb_i2c.h | 19 |
4 files changed, 50 insertions, 14 deletions
diff --git a/board/hammer/board.h b/board/hammer/board.h index f342acf06e..3bb4d6c0f4 100644 --- a/board/hammer/board.h +++ b/board/hammer/board.h @@ -128,6 +128,10 @@ #define CONFIG_BOARD_PRE_INIT #define CONFIG_WATCHDOG_HELP +/* Enlarge the allowed write count */ +#undef CONFIG_USB_I2C_MAX_WRITE_COUNT +#define CONFIG_USB_I2C_MAX_WRITE_COUNT 124 + /* No lid switch */ #undef CONFIG_LID_SWITCH diff --git a/common/usb_i2c.c b/common/usb_i2c.c index 4c8350e910..64d7135a89 100644 --- a/common/usb_i2c.c +++ b/common/usb_i2c.c @@ -50,12 +50,32 @@ static void usb_i2c_write_packet(struct usb_i2c_config const *config, QUEUE_ADD_UNITS(config->tx_queue, config->buffer, count); } -void usb_i2c_deferred(struct usb_i2c_config const *config) +static uint8_t usb_i2c_executable(struct usb_i2c_config const *config) { /* - * And if there is a USB packet waiting we process it and generate a - * response. + * In order to support larger write payload, we need to peek + * the queue to see if we need to wait for more data. */ + + uint8_t write_count; + + 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. + */ + config->buffer[0] = USB_I2C_SUCCESS; + config->buffer[1] = 0; + usb_i2c_write_packet(config, 4); + return 0; + } + return 1; +} + +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; /* Convert 7-bit slave address to chromium EC 8-bit address. */ @@ -70,8 +90,8 @@ void usb_i2c_deferred(struct usb_i2c_config const *config) if (!count || (!read_count && !write_count)) return; - if (write_count > USB_I2C_MAX_WRITE_COUNT || - write_count != (count - 4)) { + if (write_count > CONFIG_USB_I2C_MAX_WRITE_COUNT || + write_count != (count - 4)) { config->buffer[0] = USB_I2C_WRITE_COUNT_INVALID; } else if (read_count > USB_I2C_MAX_READ_COUNT) { config->buffer[0] = USB_I2C_READ_COUNT_INVALID; @@ -86,10 +106,16 @@ void usb_i2c_deferred(struct usb_i2c_config const *config) (uint8_t *)(config->buffer + 2), read_count, I2C_XFER_SINGLE)); } - usb_i2c_write_packet(config, read_count + 4); } +void usb_i2c_deferred(struct usb_i2c_config const *config) +{ + /* Check if we can proceed the queue. */ + if (usb_i2c_executable(config)) + usb_i2c_execute(config); +} + static void usb_i2c_written(struct consumer const *consumer, size_t count) { struct usb_i2c_config const *config = diff --git a/include/config.h b/include/config.h index b08f9296fa..f628673bd1 100644 --- a/include/config.h +++ b/include/config.h @@ -2646,6 +2646,9 @@ /* USB I2C config */ #undef CONFIG_USB_I2C +/* Allowed write count for USB over I2C */ +#define CONFIG_USB_I2C_MAX_WRITE_COUNT 60 + /*****************************************************************************/ /* USB Power monitoring interface config */ #undef CONFIG_USB_POWER diff --git a/include/usb_i2c.h b/include/usb_i2c.h index a1fe5f10db..335550b66e 100644 --- a/include/usb_i2c.h +++ b/include/usb_i2c.h @@ -23,12 +23,13 @@ * * slave address: 1 byte, i2c 7-bit bus address * - * write count: 1 byte, zero based count of bytes to write + * write count: 1 byte, zero based count of bytes to write. If write + * count exceed 60 bytes, following packets are expected + * to continue the payload without header. * * read count: 1 byte, zero based count of bytes to read * - * data: write payload up to 60 bytes of data to write, - * length must match write count + * data: payload of data to write. * * Response: * +-------------+---+---+-----------------------+ @@ -41,7 +42,7 @@ * 0x0002: Busy, try again * This can happen if someone else has acquired the shared memory * buffer that the I2C driver uses as /dev/null - * 0x0003: Write count invalid (> 60 bytes, or mismatch with payload) + * 0x0003: Write count invalid (mismatch with merged payload) * 0x0004: Read count invalid (> 60 bytes) * 0x0005: The port specified is invalid. * 0x8000: Unknown error mask @@ -63,10 +64,11 @@ enum usb_i2c_error { }; -#define USB_I2C_MAX_WRITE_COUNT 60 #define USB_I2C_MAX_READ_COUNT 60 +#define USB_I2C_CONFIG_BUFFER_SIZE \ + ((CONFIG_USB_I2C_MAX_WRITE_COUNT+4) > USB_MAX_PACKET_SIZE ? \ + (CONFIG_USB_I2C_MAX_WRITE_COUNT+4) : USB_MAX_PACKET_SIZE) -BUILD_ASSERT(USB_MAX_PACKET_SIZE == (1 + 1 + 1 + 1 + USB_I2C_MAX_WRITE_COUNT)); BUILD_ASSERT(USB_MAX_PACKET_SIZE == (2 + 1 + 1 + USB_I2C_MAX_READ_COUNT)); /* @@ -105,7 +107,8 @@ extern struct consumer_ops const usb_i2c_consumer_ops; INTERFACE_NAME, \ ENDPOINT) \ static uint16_t \ - CONCAT2(NAME, _buffer_)[USB_MAX_PACKET_SIZE/2]; \ + CONCAT2(NAME, _buffer_) \ + [USB_I2C_CONFIG_BUFFER_SIZE / 2]; \ static void CONCAT2(NAME, _deferred_)(void); \ DECLARE_DEFERRED(CONCAT2(NAME, _deferred_)); \ static struct queue const CONCAT2(NAME, _to_usb_); \ @@ -134,7 +137,7 @@ extern struct consumer_ops const usb_i2c_consumer_ops; QUEUE_DIRECT(USB_MAX_PACKET_SIZE, uint8_t, \ null_producer, CONCAT2(NAME, _usb_).consumer); \ static struct queue const CONCAT3(usb_to_, NAME, _) = \ - QUEUE_DIRECT(USB_MAX_PACKET_SIZE, uint8_t, \ + QUEUE_DIRECT(CONFIG_USB_I2C_MAX_WRITE_COUNT+4, uint8_t, \ CONCAT2(NAME, _usb_).producer, NAME.consumer); \ static void CONCAT2(NAME, _deferred_)(void) \ { usb_i2c_deferred(&NAME); } |