From 241cc626850175acac7a2e95cddbeb269f75c1ba Mon Sep 17 00:00:00 2001 From: Randall Spangler Date: Mon, 14 Jul 2014 16:12:32 -0700 Subject: samus: add options for device passthru and interface This allows sending host commands to the PD chip through the EC. The --interface option allows forcing a particular host interface. This is necessary at present because the crosec device driver doesn't support host protocol v3 so only has 8-bit command numbers. BUG=chrome-os-partner:30079 BRANCH=none TEST=from EC console, ectool version -> prints EC version ectool --interface=lpc --dev=0 version -> prints EC version ectool --interface=lpc --dev=1 version -> prints PD version ectool --interface=lpc --dev=2 version -> prints error ectool --interface=i2c version -> can't find EC ectool --interface=dev version -> prints EC version Change-Id: I9dd10578dac77e3e104d19e2f37759814eec6ca2 Signed-off-by: Randall Spangler Reviewed-on: https://chromium-review.googlesource.com/207948 --- util/burn_my_ec.c | 2 +- util/comm-dev.c | 2 +- util/comm-host.c | 30 +++++++++++++++++++++++------- util/comm-host.h | 36 +++++++++++++++++++++++++++++++----- util/comm-i2c.c | 2 +- util/comm-lpc.c | 4 ++-- util/comm-mec1322.c | 4 ++-- util/ectool.c | 31 +++++++++++++++++++++++-------- 8 files changed, 84 insertions(+), 27 deletions(-) (limited to 'util') diff --git a/util/burn_my_ec.c b/util/burn_my_ec.c index 622ab48243..720d89ed93 100644 --- a/util/burn_my_ec.c +++ b/util/burn_my_ec.c @@ -130,7 +130,7 @@ int main(int argc, char *argv[]) { extern uint8_t data[] asm("_payload_start"); - if (comm_init() < 0) + if (comm_init(COMM_ALL) < 0) return -3; flash_partition(EC_IMAGE_RW, data + CONFIG_FW_RW_OFF, diff --git a/util/comm-dev.c b/util/comm-dev.c index eb3a4f9b47..ab4f9bca9e 100644 --- a/util/comm-dev.c +++ b/util/comm-dev.c @@ -102,7 +102,7 @@ int comm_init_dev(void) return 3; } - ec_command = ec_command_dev; + ec_command_proto = ec_command_dev; if (ec_readmem_dev(EC_MEMMAP_ID, 2, version) == 2 && version[0] == 'E' && version[1] == 'C') ec_readmem = ec_readmem_dev; diff --git a/util/comm-host.c b/util/comm-host.c index d0ab376aa9..3f8c70a4e7 100644 --- a/util/comm-host.c +++ b/util/comm-host.c @@ -11,15 +11,16 @@ #include "comm-host.h" #include "ec_commands.h" -int (*ec_command)(int command, int version, - const void *outdata, int outsize, - void *indata, int insize); +int (*ec_command_proto)(int command, int version, + const void *outdata, int outsize, + void *indata, int insize); int (*ec_readmem)(int offset, int bytes, void *dest); int ec_max_outsize, ec_max_insize; void *ec_outbuf; void *ec_inbuf; +static int command_offset; int comm_init_dev(void) __attribute__((weak)); int comm_init_lpc(void) __attribute__((weak)); @@ -58,21 +59,36 @@ static int fake_readmem(int offset, int bytes, void *dest) return EC_MEMMAP_TEXT_MAX - 1; } -int comm_init(void) +void set_command_offset(int offset) +{ + command_offset = offset; +} + +int ec_command(int command, int version, + const void *outdata, int outsize, + void *indata, int insize) +{ + /* Offset command code to support sub-devices */ + return ec_command_proto(command_offset + command, version, + outdata, outsize, + indata, insize); +} + +int comm_init(int interfaces) { /* Default memmap access */ ec_readmem = fake_readmem; /* Prefer new /dev method */ - if (comm_init_dev && !comm_init_dev()) + if ((interfaces & COMM_DEV) && comm_init_dev && !comm_init_dev()) goto init_ok; /* Fallback to direct LPC on x86 */ - if (comm_init_lpc && !comm_init_lpc()) + if ((interfaces & COMM_LPC) && comm_init_lpc && !comm_init_lpc()) goto init_ok; /* Fallback to direct i2c on ARM */ - if (comm_init_i2c && !comm_init_i2c()) + if ((interfaces & COMM_I2C) && comm_init_i2c && !comm_init_i2c()) goto init_ok; /* Give up */ diff --git a/util/comm-host.h b/util/comm-host.h index 1e01d58e40..30c6acee67 100644 --- a/util/comm-host.h +++ b/util/comm-host.h @@ -25,19 +25,45 @@ extern int ec_max_outsize, ec_max_insize; extern void *ec_outbuf; extern void *ec_inbuf; +/* Interfaces to allow for comm_init() */ +enum comm_interface { + COMM_DEV = (1 << 0), + COMM_LPC = (1 << 1), + COMM_I2C = (1 << 2), + COMM_ALL = -1 +}; + /** * Perform initializations needed for subsequent requests * - * returns 0 in case of success or error code. */ -int comm_init(void); + * @param interfaces Interfaces to try; use COMM_ALL to try all of them. + * @return 0 in case of success, or error code. + */ +int comm_init(int interfaces); /** * Send a command to the EC. Returns the length of output data returned (0 if * none), or negative on error. */ -extern int (*ec_command)(int command, int version, - const void *outdata, int outsize, /* to the EC */ - void *indata, int insize); /* from the EC */ +int ec_command(int command, int version, + const void *outdata, int outsize, /* to the EC */ + void *indata, int insize); /* from the EC */ + +/** + * Set the offset to be applied to the command number when ec_command() calls + * ec_command_proto(). + */ +void set_command_offset(int offset); + +/** + * Send a command to the EC. Returns the length of output data returned (0 if + * none), or negative on error. This is the low-level interface implemented + * by the protocol-specific driver. DO NOT call this version directly from + * anywhere but ec_command(), or the --device option will not work. + */ +extern int (*ec_command_proto)(int command, int version, + const void *outdata, int outsize, /* to EC */ + void *indata, int insize); /* from EC */ /** * Return the content of the EC information area mapped as "memory". diff --git a/util/comm-i2c.c b/util/comm-i2c.c index b305823198..a6fc8691dd 100644 --- a/util/comm-i2c.c +++ b/util/comm-i2c.c @@ -206,7 +206,7 @@ int comm_init_i2c(void) free(file_path); - ec_command = ec_command_i2c; + ec_command_proto = ec_command_i2c; ec_max_outsize = ec_max_insize = EC_PROTO2_MAX_PARAM_SIZE; return 0; diff --git a/util/comm-lpc.c b/util/comm-lpc.c index 25f0bea4c6..06912af1f2 100644 --- a/util/comm-lpc.c +++ b/util/comm-lpc.c @@ -289,7 +289,7 @@ int comm_init_lpc(void) if (i & EC_HOST_CMD_FLAG_VERSION_3) { /* Protocol version 3 */ - ec_command = ec_command_lpc_3; + ec_command_proto = ec_command_lpc_3; ec_max_outsize = EC_LPC_HOST_PACKET_SIZE - sizeof(struct ec_host_request); ec_max_insize = EC_LPC_HOST_PACKET_SIZE - @@ -297,7 +297,7 @@ int comm_init_lpc(void) } else if (i & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) { /* Protocol version 2 */ - ec_command = ec_command_lpc; + ec_command_proto = ec_command_lpc; ec_max_outsize = ec_max_insize = EC_PROTO2_MAX_PARAM_SIZE; } else { diff --git a/util/comm-mec1322.c b/util/comm-mec1322.c index 02b8ee775c..70e4f3ff89 100644 --- a/util/comm-mec1322.c +++ b/util/comm-mec1322.c @@ -342,7 +342,7 @@ int comm_init_lpc(void) if (i & EC_HOST_CMD_FLAG_VERSION_3) { /* Protocol version 3 */ - ec_command = ec_command_lpc_3; + ec_command_proto = ec_command_lpc_3; ec_max_outsize = EC_LPC_HOST_PACKET_SIZE - sizeof(struct ec_host_request); ec_max_insize = EC_LPC_HOST_PACKET_SIZE - @@ -350,7 +350,7 @@ int comm_init_lpc(void) } else if (i & EC_HOST_CMD_FLAG_LPC_ARGS_SUPPORTED) { /* Protocol version 2 */ - ec_command = ec_command_lpc; + ec_command_proto = ec_command_lpc; ec_max_outsize = ec_max_insize = EC_PROTO2_MAX_PARAM_SIZE; } else { diff --git a/util/ectool.c b/util/ectool.c index 36f612d5d8..89c88104a1 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -25,12 +25,13 @@ /* Command line options */ enum { - OPT_HELP = '?', OPT_DEV = 1000, + OPT_INTERFACE, }; static struct option long_opts[] = { {"dev", 1, 0, OPT_DEV}, + {"interface", 1, 0, OPT_INTERFACE}, {NULL, 0, 0, 0} }; @@ -216,7 +217,8 @@ int parse_bool(const char *s, int *dest) void print_help(const char *prog, int print_cmds) { - printf("Usage: %s [--dev=n] [params]\n\n", + printf("Usage: %s [--dev=n] [--interface=dev|lpc|i2c] " + "[params]\n\n", prog); if (print_cmds) puts(help_str); @@ -4540,6 +4542,7 @@ int main(int argc, char *argv[]) { const struct command *cmd; int dev = 0; + int interfaces = COMM_ALL; int rv = 1; int parse_error = 0; char *e; @@ -4561,6 +4564,19 @@ int main(int argc, char *argv[]) parse_error = 1; } break; + + case OPT_INTERFACE: + if (!strcasecmp(optarg, "dev")) { + interfaces = COMM_DEV; + } else if (!strcasecmp(optarg, "lpc")) { + interfaces = COMM_LPC; + } else if (!strcasecmp(optarg, "i2c")) { + interfaces = COMM_I2C; + } else { + fprintf(stderr, "Invalid --interface\n"); + parse_error = 1; + } + break; } } @@ -4574,11 +4590,10 @@ int main(int argc, char *argv[]) exit(1); } - /* - * --dev support is coming in the next patch. For now this is a - * placeholder used in testing getopt_long() - */ - if (dev != 0) { + /* Handle sub-devices command offset */ + if (dev > 0 && dev < 4) { + set_command_offset(EC_CMD_PASSTHRU_OFFSET(dev)); + } else if (dev != 0) { fprintf(stderr, "Bad device number %d\n", dev); parse_error = 1; } @@ -4593,7 +4608,7 @@ int main(int argc, char *argv[]) exit(1); } - if (comm_init()) { + if (comm_init(interfaces)) { fprintf(stderr, "Couldn't find EC\n"); goto out; } -- cgit v1.2.1