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 <rspangler@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/207948
This commit is contained in:
Randall Spangler
2014-07-14 16:12:32 -07:00
committed by chrome-internal-fetch
parent 9ef82030e6
commit 241cc62685
8 changed files with 84 additions and 27 deletions

View File

@@ -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,

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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".

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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] <command> [params]\n\n",
printf("Usage: %s [--dev=n] [--interface=dev|lpc|i2c] <command> "
"[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;
}