summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaveh Jalali <caveh@chromium.org>2021-09-21 17:14:46 -0700
committerCommit Bot <commit-bot@chromium.org>2021-10-01 22:25:16 +0000
commit0a807638423e72032e0e4e21f0dfa0059a9e94a6 (patch)
treec3c5cb35947ebc024fc27cac785ddd27750f6818
parent70b07f8504ba32ace9292b36e0bc22fa2319c4e9 (diff)
downloadchrome-ec-0a807638423e72032e0e4e21f0dfa0059a9e94a6.tar.gz
ectool: Implement I2C speed control command
This adds the new "i2cspeed" command. The command takes an I2C port (bus) number as an argument. Without a 2nd argument, the current I2C speed is reported. If a 2nd argument is given, the I2C bus speed accordingly, the unit is assumed to be Kbps. In practice, only 3 speeds are supported: 100, 400, 1000 kHz. BRANCH=none BUG=b:201039003 TEST=with follow-on patches, switched I2C bus speed between 400 kHz and 1 MHz using ectool. Change-Id: I80cd436c85c368f13357a4a80c3179e1fb483cb1 Signed-off-by: Caveh Jalali <caveh@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3181508 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Boris Mittelberg <bmbm@google.com>
-rw-r--r--util/ectool.c3
-rw-r--r--util/ectool.h1
-rw-r--r--util/ectool_i2c.c90
3 files changed, 94 insertions, 0 deletions
diff --git a/util/ectool.c b/util/ectool.c
index 8d338c04ff..01d3605afd 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -184,6 +184,8 @@ const char help_str[] =
" Protect EC's I2C bus\n"
" i2cread\n"
" Read I2C bus\n"
+ " i2cspeed <port> [speed]\n"
+ " Get or set EC's I2C bus speed\n"
" i2cwrite\n"
" Write I2C bus\n"
" i2cxfer <port> <peripheral_addr> <read_count> [write bytes...]\n"
@@ -10444,6 +10446,7 @@ const struct command commands[] = {
{"locatechip", cmd_locate_chip},
{"i2cprotect", cmd_i2c_protect},
{"i2cread", cmd_i2c_read},
+ {"i2cspeed", cmd_i2c_speed},
{"i2cwrite", cmd_i2c_write},
{"i2cxfer", cmd_i2c_xfer},
{"infopddev", cmd_pd_device_info},
diff --git a/util/ectool.h b/util/ectool.h
index a0cc0c72a0..c76e1652cc 100644
--- a/util/ectool.h
+++ b/util/ectool.h
@@ -46,5 +46,6 @@ extern int ascii_mode;
int cmd_i2c_protect(int argc, char *argv[]);
int cmd_i2c_read(int argc, char *argv[]);
+int cmd_i2c_speed(int argc, char *argv[]);
int cmd_i2c_write(int argc, char *argv[]);
int cmd_i2c_xfer(int argc, char *argv[]);
diff --git a/util/ectool_i2c.c b/util/ectool_i2c.c
index cf016d44a8..97e47e6e85 100644
--- a/util/ectool_i2c.c
+++ b/util/ectool_i2c.c
@@ -4,6 +4,7 @@
*/
#include <ctype.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -122,6 +123,7 @@ static void cmd_i2c_help(void)
{
fprintf(stderr,
" Usage: i2cread <8 | 16> <port> <addr8> <offset>\n"
+ " Usage: i2cspeed <port> [speed in kHz]\n"
" Usage: i2cwrite <8 | 16> <port> <addr8> <offset> <data>\n"
" Usage: i2cxfer <port> <addr7> <read_count> [bytes...]\n"
" <port> i2c port number\n"
@@ -319,3 +321,91 @@ int cmd_i2c_xfer(int argc, char *argv[])
return 0;
}
+
+static int i2c_get(int port)
+{
+ struct ec_params_i2c_control p;
+ struct ec_response_i2c_control r;
+ uint16_t speed_khz;
+ int rv;
+
+ memset(&p, 0, sizeof(p));
+ p.port = port;
+ p.cmd = EC_I2C_CONTROL_GET_SPEED;
+
+ rv = ec_command(EC_CMD_I2C_CONTROL, 0, &p, sizeof(p), &r, sizeof(r));
+ if (rv < 0)
+ return rv;
+
+ speed_khz = r.cmd_response.speed_khz;
+ if (speed_khz == EC_I2C_CONTROL_SPEED_UNKNOWN)
+ printf("I2C port %d: speed: unknown\n", port);
+ else
+ printf("I2C port %d: speed: %u kHz\n", port, speed_khz);
+
+ return 0;
+}
+
+static int i2c_set(int port, int new_speed_khz)
+{
+ struct ec_params_i2c_control p;
+ struct ec_response_i2c_control r;
+ uint16_t old_speed_khz;
+ int rv;
+
+ if ((new_speed_khz == EC_I2C_CONTROL_SPEED_UNKNOWN) ||
+ (new_speed_khz < 0 || new_speed_khz > UINT16_MAX)) {
+ fprintf(stderr, "I2C speed %d kHz is not supported\n",
+ new_speed_khz);
+ return -1;
+ }
+
+ memset(&p, 0, sizeof(p));
+ p.port = port;
+ p.cmd = EC_I2C_CONTROL_SET_SPEED;
+ p.cmd_params.speed_khz = new_speed_khz;
+
+ rv = ec_command(EC_CMD_I2C_CONTROL, 0, &p, sizeof(p), &r, sizeof(r));
+ if (rv < 0)
+ return rv;
+
+ old_speed_khz = r.cmd_response.speed_khz;
+ if (old_speed_khz == EC_I2C_CONTROL_SPEED_UNKNOWN) {
+ printf("Port %d speed set to %d kHz\n", port, new_speed_khz);
+ } else {
+ printf("Port %d speed changed from %u kHz to %d kHz\n", port,
+ old_speed_khz,
+ new_speed_khz);
+ }
+
+ return 0;
+}
+
+int cmd_i2c_speed(int argc, char *argv[])
+{
+ unsigned int port, speed;
+ char *e;
+
+ if (argc < 2 || argc > 3) {
+ cmd_i2c_help();
+ return -1;
+ }
+
+ port = strtol(argv[1], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad port.\n");
+ return -1;
+ }
+
+ if (argc == 2)
+ return i2c_get(port);
+
+ speed = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad speed. "
+ "Typical speeds are one of {100,400,1000}.\n");
+ return -1;
+ }
+
+ return i2c_set(port, speed);
+}