diff options
author | Jan Dabros <jsd@semihalf.com> | 2020-10-26 08:12:47 +0100 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-11-12 22:30:02 +0000 |
commit | 9d6969f0f669da3a367bc8c2da7f65734759b4e4 (patch) | |
tree | 0a85ce5499f788e4a7fa63b558d1ed39879ad97d | |
parent | d3ce1d065e682b2afe6868a485942a57b2415553 (diff) | |
download | chrome-ec-9d6969f0f669da3a367bc8c2da7f65734759b4e4.tar.gz |
i2c_master: Add i2cxfer raw command
GL3590 USB3.1 hub has i2c interface, which behaves different from
majority of i2c slaves. While write operation is the same, this chip
doesn't support repeated-start sequence for reads.
New command allows to create i2c frames in a more flexible way. User may
specify how many (if any) bytes to write and then how many bytes to
read.
Since the raw option is for debugging and won't be commonly used,
do not include it by default to save space on flash -
use #define CONFIG_CMD_I2C_XFER_RAW built with the raw option.
For now, it will be defined only for servo_v4p1.
BUG=b:150323106
BRANCH=master
TEST=buildall.
Verify that reading i2c data from non-gl3590 devices is not
affected by this change.
For usual write16 (0x0201) at offset 0x4 from device 0x24:
i2cxfer raw 1 0x24 0 0x4 0x1 0x2.
When reading from GL3590 device, two operations will be required:
i2cxfer raw 1 0x50 0 0x10
i2cxfer raw 1 0x50 8
Signed-off-by: Jan Dabros <jsd@semihalf.com>
Change-Id: Ifd9ee5184490eb8de383c9468b0152e6f993d7c9
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2505780
Reviewed-by: Brian Nemec <bnemec@chromium.org>
Commit-Queue: Brian Nemec <bnemec@chromium.org>
Tested-by: Brian Nemec <bnemec@chromium.org>
-rw-r--r-- | board/servo_v4p1/board.h | 3 | ||||
-rw-r--r-- | common/i2c_master.c | 65 | ||||
-rw-r--r-- | include/config.h | 1 |
3 files changed, 68 insertions, 1 deletions
diff --git a/board/servo_v4p1/board.h b/board/servo_v4p1/board.h index 621ea5fa8e..02bc4431ef 100644 --- a/board/servo_v4p1/board.h +++ b/board/servo_v4p1/board.h @@ -217,6 +217,9 @@ #define PD_MAX_POWER_MW 60000 #define PD_MAX_CURRENT_MA 3000 #define PD_MAX_VOLTAGE_MV 20000 + +/* Add the raw option to the i2c_xfer command */ +#define CONFIG_CMD_I2C_XFER_RAW #else #undef CONFIG_CMD_I2C_XFER #undef CONFIG_USB_POWER_DELIVERY diff --git a/common/i2c_master.c b/common/i2c_master.c index 23164720b5..09d446bf94 100644 --- a/common/i2c_master.c +++ b/common/i2c_master.c @@ -1514,7 +1514,66 @@ static int command_i2cxfer(int argc, char **argv) else rv = i2c_write16(port, addr_flags, offset, v); +#ifdef CONFIG_CMD_I2C_XFER_RAW + } else if (strcasecmp(argv[1], "raw") == 0) { + /* <port> <slave_addr> <read_count> [write_bytes..] */ + int i; + int write_count = 0, read_count = 0; + int xferflags = I2C_XFER_START; + + read_count = offset; + if (read_count < 0 || read_count > sizeof(data)) + return EC_ERROR_PARAM5; + + if (argc >= 6) { + /* Parse bytes to write */ + argc -= 5; + argv += 5; + write_count = argc; + if (write_count > sizeof(data)) { + ccprintf("Too many bytes to write\n"); + return EC_ERROR_PARAM_COUNT; + } + + for (i = 0; i < write_count; i++) { + data[i] = strtoi(argv[i], &e, 0); + if (*e) { + ccprintf("Bad write byte %d\n", i); + return EC_ERROR_INVAL; + } + } + } + if (write_count) { + if (read_count == 0) + xferflags |= I2C_XFER_STOP; + ccprintf("Writing %d bytes\n", write_count); + i2c_lock(port, 1); + rv = i2c_xfer_unlocked(port, + addr_flags, + data, write_count, + NULL, 0, + xferflags); + if (rv || read_count == 0) { + i2c_lock(port, 0); + return rv; + } + } + if (read_count) { + ccprintf("Reading %d bytes\n", read_count); + if (write_count == 0) + i2c_lock(port, 1); + rv = i2c_xfer_unlocked(port, + addr_flags, + NULL, 0, + data, read_count, + I2C_XFER_START | I2C_XFER_STOP); + i2c_lock(port, 0); + if (!rv) + ccprintf("Data: %ph\n", + HEX_BUF(data, read_count)); + } +#endif /* CONFIG_CMD_I2C_XFER_RAW */ } else { return EC_ERROR_PARAM1; } @@ -1522,7 +1581,11 @@ static int command_i2cxfer(int argc, char **argv) return rv; } DECLARE_CONSOLE_COMMAND(i2cxfer, command_i2cxfer, - "r/r16/rlen/w/w16 port addr offset [value | len]", + "r/r16/rlen/w/w16 port addr offset [value | len]" +#ifdef CONFIG_CMD_I2C_XFER_RAW + "\nraw port addr read_count [bytes_to_write..]" +#endif /* CONFIG_CMD_I2C_XFER_RAW */ + , "Read write I2C"); #endif diff --git a/include/config.h b/include/config.h index 47e6641645..b3a92c859d 100644 --- a/include/config.h +++ b/include/config.h @@ -1345,6 +1345,7 @@ #undef CONFIG_CMD_I2C_STRESS_TEST_CHARGER #undef CONFIG_CMD_I2C_STRESS_TEST_TCPC #define CONFIG_CMD_I2C_XFER +#undef CONFIG_CMD_I2C_XFER_RAW #define CONFIG_CMD_IDLE_STATS #undef CONFIG_CMD_ILIM #define CONFIG_CMD_INA |