diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-04-30 12:16:39 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-05-09 16:36:53 -0700 |
commit | 1e4b0b6194b3ff16233e824daa4bab18a8dcce0f (patch) | |
tree | de57b1a8f1bbda6be2f515ae2a59882ef6365e23 /util | |
parent | d2ca284bc6da637aabb0dbfd4a4d67451646f23a (diff) | |
download | chrome-ec-1e4b0b6194b3ff16233e824daa4bab18a8dcce0f.tar.gz |
Implement I2C passthru command
This is a revised version of passthru which more closely resembles the
kernel interface. It allows multiple read/write messages in a single
transaction, and sends back one accumulated result.
BUG=chrome-os-partner:18778
BRANCH=none
TEST=On link, from root shell:
ectool i2cxfer 0 0xb 6 0x21
Read bytes: 0x05 0x41 0x52 0x52 0x4f 0x57
(I did not actually run this with the updated code)
On pit, in U-Boot:
Read i2c values:
Peach # crosec i2c md 48 0
0000: 00 00 3e 00 12 20 4b bf ff ff 20 00 1e 1e 1e 1f ..>.. K... .....
Peach # crosec i2c md 48 0 20
0000: 00 00 3e 00 12 20 4b bf ff ff 20 00 1e 1e 1e 1f ..>.. K... .....
0010: 1f 1f 1f 1f 1f 1f 20 00 00 07 00 00 00 00 00 00 ...... .........
Update value at offset 10:
Peach # crosec i2c mw 48 10 4
Peach # crosec i2c md 48 0 20
0000: 00 00 3e 00 12 00 0b 1f 1f ff 20 00 1e 1e 1e 1f ..>....... .....
0010: 04 1f 1f 1f 1f 1f 20 00 00 07 00 00 00 00 00 00 ...... .........
Peach #
On pit, in kernel:
localhost ~ # i2cdetect -y -a -r 20
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
localhost ~ # i2cdump -f -y 20 0x48
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 3e 00 12 00 0b 1f 1f ff 20 00 1e 1e 1e 1f ..>.?.???. .????
10: 1f 1f 0e 1f 1f 0e 20 00 00 07 00 00 00 00 00 00 ?????? ..?......
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
localhost ~ # i2cset -f -y 20 0x48 0x10 0
localhost ~ # i2cdump -f -y 20 0x48
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 3e 00 12 00 0b 1f 1f ff 20 00 1e 1e 1e 1f ..>.?.???. .????
10: 00 1f 0e 1f 1f 0e 20 00 00 07 00 00 00 00 00 00 .????? ..?......
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
localhost ~ # i2cset -f -y 20 0x48 0x10 0x1f
localhost ~ # i2cdump -f -y 20 0x48
No size specified (using byte-data access)
0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef
00: 00 00 3e 00 12 00 0b 1f 1f ff 20 00 1e 1e 1e 1f ..>.?.???. .????
10: 1f 1f 0e 1f 1f 0e 20 00 00 07 00 00 00 00 00 00 ?????? ..?......
Change-Id: I14d47e1712828f726ac5caddc4beede251570ad3
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Updated to simplify protocol:
Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/49958
Commit-Queue: Doug Anderson <dianders@chromium.org>
Reviewed-by: Doug Anderson <dianders@chromium.org>
Tested-by: Doug Anderson <dianders@chromium.org>
Diffstat (limited to 'util')
-rw-r--r-- | util/ectool.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/util/ectool.c b/util/ectool.c index 0315b6dbb1..52b4df94d1 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -94,6 +94,8 @@ const char help_str[] = " Read I2C bus\n" " i2cwrite\n" " Write I2C bus\n" + " i2cxfer <port> <slave_addr> <read_count> [write bytes...]\n" + " Perform I2C transfer on EC's I2C bus\n" " keyscan <beat_us> <filename>\n" " Test low-level key scanning\n" " lightbar [CMDS]\n" @@ -1933,6 +1935,10 @@ int cmd_i2c_read(int argc, char *argv[]) return -1; } + /* + * TODO: use I2C_XFER command if supported, then fall back to I2C_READ + */ + rv = ec_command(EC_CMD_I2C_READ, 0, &p, sizeof(p), &r, sizeof(r)); if (rv < 0) @@ -1987,6 +1993,10 @@ int cmd_i2c_write(int argc, char *argv[]) return -1; } + /* + * TODO: use I2C_XFER command if supported, then fall back to I2C_WRITE + */ + rv = ec_command(EC_CMD_I2C_WRITE, 0, &p, sizeof(p), NULL, 0); if (rv < 0) @@ -1998,6 +2008,116 @@ int cmd_i2c_write(int argc, char *argv[]) } +int cmd_i2c_xfer(int argc, char *argv[]) +{ + union { + struct ec_params_i2c_passthru p; + uint8_t outbuf[EC_HOST_PARAM_SIZE]; + } params; + union { + struct ec_response_i2c_passthru r; + uint8_t inbuf[EC_HOST_PARAM_SIZE]; + } response; + struct ec_params_i2c_passthru *p = ¶ms.p; + struct ec_response_i2c_passthru *r = &response.r; + struct ec_params_i2c_passthru_msg *msg = p->msg; + unsigned int addr; + uint8_t *pdata; + char *e; + int read_len, write_len; + int size; + int rv, i; + + if (argc < 4) { + fprintf(stderr, + "Usage: %s <port> <slave_addr> <read_count> " + "[write bytes...]\n", argv[0]); + return -1; + } + + p->port = strtol(argv[1], &e, 0); + if (e && *e) { + fprintf(stderr, "Bad port.\n"); + return -1; + } + + addr = strtol(argv[2], &e, 0) & 0x7f; + if (e && *e) { + fprintf(stderr, "Bad slave address.\n"); + return -1; + } + + read_len = strtol(argv[3], &e, 0); + if (e && *e) { + fprintf(stderr, "Bad read length.\n"); + return -1; + } + + /* Skip over params to bytes to write */ + argc -= 4; + argv += 4; + write_len = argc; + p->num_msgs = (read_len != 0) + (write_len != 0); + + size = sizeof(*p) + p->num_msgs * sizeof(*msg); + if (size + write_len > sizeof(params)) { + fprintf(stderr, "Params too large for buffer\n"); + return -1; + } + if (sizeof(*r) + read_len > sizeof(response)) { + fprintf(stderr, "Read length too big for buffer\n"); + return -1; + } + + pdata = (uint8_t *)p + size; + if (write_len) { + msg->addr_flags = addr; + msg->len = write_len; + + for (i = 0; i < write_len; i++) { + pdata[i] = strtol(argv[i], &e, 0); + if (e && *e) { + fprintf(stderr, "Bad write byte %d\n", i); + return -1; + } + } + msg++; + } + + if (read_len) { + msg->addr_flags = addr | EC_I2C_FLAG_READ; + msg->len = read_len; + } + + rv = ec_command(EC_CMD_I2C_PASSTHRU, 0, p, size + write_len, + r, sizeof(*r) + read_len); + if (rv < 0) + return rv; + + /* Parse response */ + if (r->i2c_status & (EC_I2C_STATUS_NAK | EC_I2C_STATUS_TIMEOUT)) { + fprintf(stderr, "Transfer failed with status=0x%x\n", + r->i2c_status); + return -1; + } + + if (rv < sizeof(*r) + read_len) { + fprintf(stderr, "Truncated read response\n"); + return -1; + } + + if (read_len) { + printf("Read bytes:"); + for (i = 0; i < read_len; i++) + printf(" %#02x", r->data[i]); + printf("\n"); + } else { + printf("Write successful.\n"); + } + + return 0; +} + int cmd_lcd_backlight(int argc, char *argv[]) { struct ec_params_switch_enable_backlight p; @@ -2787,6 +2907,7 @@ const struct command commands[] = { {"kbpress", cmd_kbpress}, {"i2cread", cmd_i2c_read}, {"i2cwrite", cmd_i2c_write}, + {"i2cxfer", cmd_i2c_xfer}, {"lightbar", cmd_lightbar}, {"keyconfig", cmd_keyconfig}, {"keyscan", cmd_keyscan}, |