From a35bfd69e9a749fbaa152937dd91a6ed407a9005 Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Fri, 28 Feb 2014 12:39:43 -0800 Subject: Add arbitrary-length read support to i2cxfer Previously, it could only read 8 or 16 bit values BUG=chrome-os-partner:26191 BRANCH=rambi TEST=manual Counted string for battery manufacturer name: > i2cxfer rlen 0 0x16 0x20 16 Data: 0653696d706c6fe1e1e1e1e1e1e1e1e1 Read lifetime data block 1 (also tests 16-bit writes) > i2cxfer w16 0 0x16 0 0x60 > i2cxfer rlen 0 0x16 0x23 32 Data: 20d2d2d2d2948700000d0a0a060a000000020000000000000000000000000000 Read lifetime data block 2 > i2cxfer w16 0 0x16 0 0x61 > i2cxfer rlen 0 0x16 0x23 27 Data: 1b0000000000010200010c02000201000100000300002008082009 8 and 16 bit reads still work > i2cxfer r 0 0x16 0x23 0x1b [27] > i2cxfer r16 0 0x16 0x23 0x001b [27] Change-Id: Ibba5aced60c0b2de04c3f86cf5fd2ab3db1b6308 Signed-off-by: Randall Spangler Reviewed-on: https://chromium-review.googlesource.com/188379 Reviewed-by: Alec Berg --- common/i2c.c | 123 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 55 insertions(+), 68 deletions(-) diff --git a/common/i2c.c b/common/i2c.c index 995d7cb7cb..f5ac9ff7f8 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -396,95 +396,82 @@ DECLARE_CONSOLE_COMMAND(i2cscan, command_scan, "Scan I2C ports for devices", NULL); - static int command_i2cxfer(int argc, char **argv) { - int rw = 0; - int port, slave_addr, offset; - int value = 0; + int port, slave_addr; + uint8_t offset; + int v = 0; + uint8_t data[32]; char *e; int rv = 0; - if (argc < 5) { - ccputs("Usage: i2cxfer r/r16/w/w16 port addr offset [value]\n"); - return EC_ERROR_UNKNOWN; - } - - if (strcasecmp(argv[1], "r") == 0) { - rw = 0; - } else if (strcasecmp(argv[1], "r16") == 0) { - rw = 1; - } else if (strcasecmp(argv[1], "w") == 0) { - rw = 2; - } else if (strcasecmp(argv[1], "w16") == 0) { - rw = 3; - } else { - ccputs("Invalid rw mode : r / w / r16 / w16\n"); - return EC_ERROR_INVAL; - } + if (argc < 5) + return EC_ERROR_PARAM_COUNT; port = strtoi(argv[2], &e, 0); - if (*e) { - ccputs("Invalid port\n"); - return EC_ERROR_INVAL; - } + if (*e) + return EC_ERROR_PARAM2; slave_addr = strtoi(argv[3], &e, 0); - if (*e) { - ccputs("Invalid slave_addr\n"); - return EC_ERROR_INVAL; - } + if (*e) + return EC_ERROR_PARAM3; offset = strtoi(argv[4], &e, 0); - if (*e) { - ccputs("Invalid addr\n"); - return EC_ERROR_INVAL; - } + if (*e) + return EC_ERROR_PARAM4; - if (rw > 1) { - if (argc < 6) { - ccputs("No write value\n"); - return EC_ERROR_INVAL; - } - value = strtoi(argv[5], &e, 0); - if (*e) { - ccputs("Invalid write value\n"); - return EC_ERROR_INVAL; - } + if (argc >= 5) { + v = strtoi(argv[5], &e, 0); + if (*e) + return EC_ERROR_PARAM5; } + if (strcasecmp(argv[1], "r") == 0) { + /* 8-bit read */ + rv = i2c_read8(port, slave_addr, offset, &v); + if (!rv) + ccprintf("0x%02x [%d]\n", v); - switch (rw) { - case 0: - rv = i2c_read8(port, slave_addr, offset, &value); - break; - case 1: - rv = i2c_read16(port, slave_addr, offset, &value); - break; - case 2: - rv = i2c_write8(port, slave_addr, offset, value); - break; - case 3: - rv = i2c_write16(port, slave_addr, offset, value); - break; - } + } else if (strcasecmp(argv[1], "r16") == 0) { + /* 16-bit read */ + rv = i2c_read16(port, slave_addr, offset, &v); + if (!rv) + ccprintf("0x%04x [%d]\n", v); + } else if (strcasecmp(argv[1], "rlen") == 0) { + /* Arbitrary length read; param5 = len */ + if (argc < 6 || v < 0 || v > sizeof(data)) + return EC_ERROR_PARAM5; - if (rv) { - ccprintf("i2c command failed\n", rv); - return rv; - } + i2c_lock(port, 1); + rv = i2c_xfer(port, slave_addr, + &offset, 1, data, v, I2C_XFER_SINGLE); + i2c_lock(port, 0); - if (rw == 0) - ccprintf("0x%02x [%d]\n", value); - else if (rw == 1) - ccprintf("0x%04x [%d]\n", value); + if (!rv) + ccprintf("Data: %.*h\n", v, data); - ccputs("ok\n"); + } else if (strcasecmp(argv[1], "w") == 0) { + /* 8-bit write */ + if (argc < 6) + return EC_ERROR_PARAM5; - return EC_SUCCESS; + rv = i2c_write8(port, slave_addr, offset, v); + + } else if (strcasecmp(argv[1], "w16") == 0) { + /* 16-bit write */ + if (argc < 6) + return EC_ERROR_PARAM5; + + rv = i2c_write16(port, slave_addr, offset, v); + + } else { + return EC_ERROR_PARAM1; + } + + return rv; } DECLARE_CONSOLE_COMMAND(i2cxfer, command_i2cxfer, - "r/r16/w/w16 port addr offset [value]", + "r/r16/rlen/w/w16 port addr offset [value | len]", "Read write I2C", NULL); -- cgit v1.2.1