summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2013-02-05 13:05:42 -0800
committerChromeBot <chrome-bot@google.com>2013-02-05 20:16:22 -0800
commit231319c08c29676ee1f35994d443c3dccf2098f5 (patch)
tree784ea3eb4290cda288380b8d31818f307039cc85
parentf4a9ffdee34f2d59b120eded5688efa3491d5ab1 (diff)
downloadchrome-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.c22
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, &reg, 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;
}