mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2026-01-10 01:21:49 +00:00
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 <rspangler@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/188379 Reviewed-by: Alec Berg <alecaberg@chromium.org>
This commit is contained in:
committed by
chrome-internal-fetch
parent
832a0c7988
commit
a35bfd69e9
135
common/i2c.c
135
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 (argc < 5)
|
||||
return EC_ERROR_PARAM_COUNT;
|
||||
|
||||
port = strtoi(argv[2], &e, 0);
|
||||
if (*e)
|
||||
return EC_ERROR_PARAM2;
|
||||
|
||||
slave_addr = strtoi(argv[3], &e, 0);
|
||||
if (*e)
|
||||
return EC_ERROR_PARAM3;
|
||||
|
||||
offset = strtoi(argv[4], &e, 0);
|
||||
if (*e)
|
||||
return EC_ERROR_PARAM4;
|
||||
|
||||
if (argc >= 5) {
|
||||
v = strtoi(argv[5], &e, 0);
|
||||
if (*e)
|
||||
return EC_ERROR_PARAM5;
|
||||
}
|
||||
|
||||
if (strcasecmp(argv[1], "r") == 0) {
|
||||
rw = 0;
|
||||
/* 8-bit read */
|
||||
rv = i2c_read8(port, slave_addr, offset, &v);
|
||||
if (!rv)
|
||||
ccprintf("0x%02x [%d]\n", v);
|
||||
|
||||
} else if (strcasecmp(argv[1], "r16") == 0) {
|
||||
rw = 1;
|
||||
/* 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;
|
||||
|
||||
i2c_lock(port, 1);
|
||||
rv = i2c_xfer(port, slave_addr,
|
||||
&offset, 1, data, v, I2C_XFER_SINGLE);
|
||||
i2c_lock(port, 0);
|
||||
|
||||
if (!rv)
|
||||
ccprintf("Data: %.*h\n", v, data);
|
||||
|
||||
} else if (strcasecmp(argv[1], "w") == 0) {
|
||||
rw = 2;
|
||||
/* 8-bit write */
|
||||
if (argc < 6)
|
||||
return EC_ERROR_PARAM5;
|
||||
|
||||
rv = i2c_write8(port, slave_addr, offset, v);
|
||||
|
||||
} else if (strcasecmp(argv[1], "w16") == 0) {
|
||||
rw = 3;
|
||||
/* 16-bit write */
|
||||
if (argc < 6)
|
||||
return EC_ERROR_PARAM5;
|
||||
|
||||
rv = i2c_write16(port, slave_addr, offset, v);
|
||||
|
||||
} else {
|
||||
ccputs("Invalid rw mode : r / w / r16 / w16\n");
|
||||
return EC_ERROR_INVAL;
|
||||
return EC_ERROR_PARAM1;
|
||||
}
|
||||
|
||||
port = strtoi(argv[2], &e, 0);
|
||||
if (*e) {
|
||||
ccputs("Invalid port\n");
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
|
||||
slave_addr = strtoi(argv[3], &e, 0);
|
||||
if (*e) {
|
||||
ccputs("Invalid slave_addr\n");
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
|
||||
offset = strtoi(argv[4], &e, 0);
|
||||
if (*e) {
|
||||
ccputs("Invalid addr\n");
|
||||
return EC_ERROR_INVAL;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
if (rv) {
|
||||
ccprintf("i2c command failed\n", rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (rw == 0)
|
||||
ccprintf("0x%02x [%d]\n", value);
|
||||
else if (rw == 1)
|
||||
ccprintf("0x%04x [%d]\n", value);
|
||||
|
||||
ccputs("ok\n");
|
||||
|
||||
return EC_SUCCESS;
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user