From c72628b8e7fa539da5a8ba249a138d57ec1aa160 Mon Sep 17 00:00:00 2001 From: Shamile Khan Date: Mon, 9 Feb 2015 15:49:05 -0800 Subject: [PATCH] Strago:Fix I2C Block Read operation. I2C Block reads were split into two i2c_xfer() calls. However, i2c_xfer() implementation for MEC does not maintain state in between calls. This was causing block read failures because the settings for the Control Register got corrupted. Fix this by calling i2c_xfer() only once. This retrieves both string size and string. Only return the string back to the user. BUG=None TEST=Tested on Braswell Ref Design BRANCH=None Change-Id: Ife8fcb66425c6198d0dcf10f74e89c001ccac49a Signed-off-by: Shamile Khan Signed-off-by: Divya Jyothi Reviewed-on: https://chromium-review.googlesource.com/260627 Reviewed-by: Randall Spangler --- chip/mec1322/i2c.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/chip/mec1322/i2c.c b/chip/mec1322/i2c.c index 372ed20130..85a8e2a02b 100644 --- a/chip/mec1322/i2c.c +++ b/chip/mec1322/i2c.c @@ -35,6 +35,9 @@ #define CTRL_ESO (1 << 6) /* Enable serial output */ #define CTRL_PIN (1 << 7) /* Pending interrupt not */ +/* Maximum transfer of a SMBUS block transfer */ +#define SMBUS_MAX_BLOCK_SIZE 32 + static task_id_t task_waiting_on_port[I2C_PORT_COUNT]; static void configure_port_speed(int port, int kbps) @@ -329,6 +332,42 @@ int i2c_get_line_levels(int port) return (MEC1322_I2C_BB_CTRL(port) >> 5) & 0x3; } +int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, + int len) +{ + int rv; + uint8_t reg, block_length; + + if ((len <= 0) || (len > SMBUS_MAX_BLOCK_SIZE)) + return EC_ERROR_INVAL; + + i2c_lock(port, 1); + + /* + * Read the counted string into the output buffer + */ + reg = offset; + rv = i2c_xfer(port, slave_addr, ®, 1, data, len, I2C_XFER_SINGLE); + if (rv) + goto exit; + + /* + * Block length is the first byte of the returned buffer + */ + block_length = MIN(data[0], len - 1); + + /* + * Move data down, then null-terminate it + */ + memmove(data, data + 1, block_length); + data[block_length] = '\0'; + +exit: + i2c_lock(port, 0); + return rv; +} + + static void i2c_init(void) { int i;