summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorHarry Cutts <hcutts@chromium.org>2019-09-25 11:20:20 -0700
committerCommit Bot <commit-bot@chromium.org>2019-10-04 06:59:27 +0000
commit5f7e4c337dae601208f308efba15ad6d9ffbe788 (patch)
treedd88337d1ede373e381fad8c6c0df91634871890 /util
parent2ee2d6fe8711f51343bb08e0fde599c2643c93e6 (diff)
downloadchrome-ec-5f7e4c337dae601208f308efba15ad6d9ffbe788.tar.gz
util/comm-i2c: Add switch to specify I2C bus
Currently, devices running CrOS EC that aren't actually the embedded controller (such as touchpad or fingerprint MCUs) can only be contacted over I2C if they are in the device tree. To avoid having to recompile the Kernel, Coreboot, or `ectool`, the `--i2c_bus` switch allows `ectool` to be used for testing as-is. BRANCH=none BUG=none TEST=Checked various commands (hello, version, inventory...) with `--i2c_bus=7`, connecting to a MAX32660. Verified that a contradictory `--interface` switch is rejected. Checked that invalid bus numbers (≥32) are rejected. Change-Id: I92f3307bbbdf88978b9f8271610a3ae222279767 Signed-off-by: Harry Cutts <hcutts@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1828064 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Diffstat (limited to 'util')
-rw-r--r--util/comm-host.c29
-rw-r--r--util/comm-host.h3
-rw-r--r--util/comm-i2c.c47
-rw-r--r--util/ectool.c28
4 files changed, 73 insertions, 34 deletions
diff --git a/util/comm-host.c b/util/comm-host.c
index 947b240bfa..dd42df1aa8 100644
--- a/util/comm-host.c
+++ b/util/comm-host.c
@@ -4,6 +4,7 @@
*/
#include <errno.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -31,7 +32,7 @@ static int command_offset;
int comm_init_dev(const char *device_name) __attribute__((weak));
int comm_init_lpc(void) __attribute__((weak));
-int comm_init_i2c(void) __attribute__((weak));
+int comm_init_i2c(int i2c_bus) __attribute__((weak));
int comm_init_servo_spi(const char *device_name) __attribute__((weak));
static int fake_readmem(int offset, int bytes, void *dest)
@@ -82,8 +83,10 @@ int ec_command(int command, int version,
indata, insize);
}
-int comm_init_alt(int interfaces, const char *device_name)
+int comm_init_alt(int interfaces, const char *device_name, int i2c_bus)
{
+ bool dev_is_cros_ec;
+
/* Default memmap access */
ec_readmem = fake_readmem;
@@ -93,17 +96,17 @@ int comm_init_alt(int interfaces, const char *device_name)
/* Do not fallback to other communication methods if target is not a
* cros_ec device */
- if (!strcmp(CROS_EC_DEV_NAME, device_name)) {
- /* Fallback to direct LPC on x86 */
- if ((interfaces & COMM_LPC) &&
- comm_init_lpc && !comm_init_lpc())
- return 0;
-
- /* Fallback to direct i2c on ARM */
- if ((interfaces & COMM_I2C) &&
- comm_init_i2c && !comm_init_i2c())
- return 0;
- }
+ dev_is_cros_ec = !strcmp(CROS_EC_DEV_NAME, device_name);
+
+ /* Fallback to direct LPC on x86 */
+ if (dev_is_cros_ec && (interfaces & COMM_LPC) &&
+ comm_init_lpc && !comm_init_lpc())
+ return 0;
+
+ /* Fallback to direct I2C */
+ if ((dev_is_cros_ec || i2c_bus != -1) && (interfaces & COMM_I2C) &&
+ comm_init_i2c && !comm_init_i2c(i2c_bus))
+ return 0;
/* Give up */
fprintf(stderr, "Unable to establish host communication\n");
diff --git a/util/comm-host.h b/util/comm-host.h
index 603f95e107..309c97eeb5 100644
--- a/util/comm-host.h
+++ b/util/comm-host.h
@@ -39,9 +39,10 @@ enum comm_interface {
*
* @param interfaces Interfaces to try; use COMM_ALL to try all of them.
* @param device_name For DEV option, the device file to use.
+ * @param i2c_bus For I2C option, the bus number to use (or -1 to autodetect).
* @return 0 in case of success, or error code.
*/
-int comm_init_alt(int interfaces, const char *device_name);
+int comm_init_alt(int interfaces, const char *device_name, int i2c_bus);
/**
* Initialize dev interface
diff --git a/util/comm-i2c.c b/util/comm-i2c.c
index d01ce3d023..d88454ee3b 100644
--- a/util/comm-i2c.c
+++ b/util/comm-i2c.c
@@ -196,33 +196,44 @@ done:
return ret;
}
-int comm_init_i2c(void)
+int comm_init_i2c(int i2c_bus)
{
char *file_path;
char buffer[64];
int i;
- /* find the device number based on the adapter name */
- for (i = 0; i < I2C_MAX_ADAPTER; i++) {
- FILE *f;
- if (asprintf(&file_path, I2C_ADAPTER_NODE,
- i, i, EC_I2C_ADDR) < 0)
+ if (i2c_bus != -1) {
+ i = i2c_bus;
+
+ if (i >= I2C_MAX_ADAPTER) {
+ fprintf(stderr, "Invalid I2C bus number %d. (The highest possible bus number is %d.)\n",
+ i, I2C_MAX_ADAPTER);
return -1;
- f = fopen(file_path, "r");
- if (f) {
- if (fgets(buffer, sizeof(buffer), f) &&
- !strncmp(buffer, I2C_ADAPTER_NAME, 6)) {
- free(file_path);
+ }
+ } else {
+ /* find the device number based on the adapter name */
+ for (i = 0; i < I2C_MAX_ADAPTER; i++) {
+ FILE *f;
+
+ if (asprintf(&file_path, I2C_ADAPTER_NODE,
+ i, i, EC_I2C_ADDR) < 0)
+ return -1;
+ f = fopen(file_path, "r");
+ if (f) {
+ if (fgets(buffer, sizeof(buffer), f) &&
+ !strncmp(buffer, I2C_ADAPTER_NAME, 6)) {
+ free(file_path);
+ fclose(f);
+ break;
+ }
fclose(f);
- break;
}
- fclose(f);
+ free(file_path);
+ }
+ if (i == I2C_MAX_ADAPTER) {
+ fprintf(stderr, "Cannot find I2C adapter\n");
+ return -1;
}
- free(file_path);
- }
- if (i == I2C_MAX_ADAPTER) {
- fprintf(stderr, "Cannot find I2C adapter\n");
- return -1;
}
if (asprintf(&file_path, I2C_NODE, i) < 0)
diff --git a/util/ectool.c b/util/ectool.c
index d73dd770ee..a78c8ba5f6 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -48,6 +48,7 @@ enum {
OPT_INTERFACE,
OPT_NAME,
OPT_ASCII,
+ OPT_I2C_BUS,
};
static struct option long_opts[] = {
@@ -55,6 +56,7 @@ static struct option long_opts[] = {
{"interface", 1, 0, OPT_INTERFACE},
{"name", 1, 0, OPT_NAME},
{"ascii", 0, 0, OPT_ASCII},
+ {"i2c_bus", 1, 0, OPT_I2C_BUS},
{NULL, 0, 0, 0}
};
@@ -352,9 +354,13 @@ int parse_bool(const char *s, int *dest)
void print_help(const char *prog, int print_cmds)
{
- printf("Usage: %s [--dev=n] [--interface=dev|i2c|lpc] ", prog);
+ printf("Usage: %s [--dev=n] [--interface=dev|i2c|lpc] [--i2c_bus=n]",
+ prog);
printf("[--name=cros_ec|cros_fp|cros_pd|cros_scp|cros_ish] [--ascii] ");
printf("<command> [params]\n\n");
+ printf(" --i2c_bus=n Specifies the number of an I2C bus to use. For\n"
+ " example, to use /dev/i2c-7, pass --i2c_bus=7.\n"
+ " Implies --interface=i2c.\n\n");
if (print_cmds)
puts(help_str);
else
@@ -9156,6 +9162,7 @@ int main(int argc, char *argv[])
const struct command *cmd;
int dev = 0;
int interfaces = COMM_ALL;
+ int i2c_bus = -1;
char device_name[41] = CROS_EC_DEV_NAME;
int rv = 1;
int parse_error = 0;
@@ -9197,12 +9204,29 @@ int main(int argc, char *argv[])
strncpy(device_name, optarg, 40);
device_name[40] = '\0';
break;
+ case OPT_I2C_BUS:
+ i2c_bus = strtoul(optarg, &e, 0);
+ if (*optarg == '\0' || (e && *e != '\0')
+ || i2c_bus < 0) {
+ fprintf(stderr, "Invalid --i2c_bus\n");
+ parse_error = 1;
+ }
+ break;
case OPT_ASCII:
ascii_mode = 1;
break;
}
}
+ if (i2c_bus != -1) {
+ if (!(interfaces & COMM_I2C)) {
+ fprintf(stderr, "--i2c_bus is specified, but --interface is set to something other than I2C\n");
+ parse_error = 1;
+ } else {
+ interfaces = COMM_I2C;
+ }
+ }
+
/* Must specify a command */
if (!parse_error && optind == argc)
parse_error = 1;
@@ -9236,7 +9260,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Could not acquire GEC lock.\n");
exit(1);
}
- if (comm_init_alt(interfaces, device_name)) {
+ if (comm_init_alt(interfaces, device_name, i2c_bus)) {
fprintf(stderr, "Couldn't find EC\n");
goto out;
}