diff options
author | Vincent Palatin <vpalatin@chromium.org> | 2013-02-05 13:05:42 -0800 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-02-05 20:16:22 -0800 |
commit | 231319c08c29676ee1f35994d443c3dccf2098f5 (patch) | |
tree | 784ea3eb4290cda288380b8d31818f307039cc85 | |
parent | f4a9ffdee34f2d59b120eded5688efa3491d5ab1 (diff) | |
download | chrome-ec-231319c08c29676ee1f35994d443c3dccf2098f5.tar.gz |
stm32: implement SMBUS-style read block/string
Add support in the I2C driver for SMBUS-style read block operations.
As defined by the SMBUS standard, a "read block" returns at most 32
bytes of data plus the size of response as the first byte.
It's used to read smart battery strings such as manufacturer or model.
Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BRANCH=none
BUG=chrome-os-partner:14314
TEST=On Spring, read the battery manufacturer and model from a kernel
patched for the smart-battery passthrough.
Change-Id: I069ce7f64414817e94516e913643d3847a29d176
Reviewed-on: https://gerrit.chromium.org/gerrit/42647
Reviewed-by: Vic Yang <victoryang@chromium.org>
Commit-Queue: Vincent Palatin <vpalatin@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r-- | chip/stm32/i2c.c | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c index b42f415273..e2f1a9fbd8 100644 --- a/chip/stm32/i2c.c +++ b/chip/stm32/i2c.c @@ -21,6 +21,9 @@ #define CPUTS(outstr) cputs(CC_I2C, outstr) #define CPRINTF(format, args...) cprintf(CC_I2C, format, ## args) +/* Maximum transfer of a SMBUS block transfer */ +#define SMBUS_MAX_BLOCK 32 + /* 8-bit I2C slave address */ #define I2C_ADDRESS 0x3c @@ -919,10 +922,23 @@ int i2c_write8(int port, int slave_addr, int offset, int data) int i2c_read_string(int port, int slave_addr, int offset, uint8_t *data, int len) { - /* TODO: implement i2c_read_block and i2c_read_string */ + int rv; + uint8_t reg, block_length; + uint8_t buffer[SMBUS_MAX_BLOCK + 1]; + + if ((len <= 0) || (len > SMBUS_MAX_BLOCK)) + return EC_ERROR_INVAL; + + reg = offset; + rv = i2c_xfer(port, slave_addr, ®, 1, buffer, SMBUS_MAX_BLOCK + 1); + if (rv) + return rv; + + /* the length of the block is the first byte of the returned buffer */ + block_length = MIN(buffer[0], len - 1); + buffer[block_length + 1] = 0; - if (len && data) - *data = 0; + memcpy(data, buffer+1, block_length + 1); return EC_SUCCESS; } |