summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Dabros <jsd@semihalf.com>2020-10-26 08:12:47 +0100
committerCommit Bot <commit-bot@chromium.org>2020-11-12 22:30:02 +0000
commit9d6969f0f669da3a367bc8c2da7f65734759b4e4 (patch)
tree0a85ce5499f788e4a7fa63b558d1ed39879ad97d
parentd3ce1d065e682b2afe6868a485942a57b2415553 (diff)
downloadchrome-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.h3
-rw-r--r--common/i2c_master.c65
-rw-r--r--include/config.h1
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