summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2012-07-15 03:03:55 +0100
committerGerrit <chrome-bot@google.com>2012-07-22 00:36:39 -0700
commitbff14cac0b17217a6be02924d109e58b3aaa50b1 (patch)
tree68e9d5b19f7a080a3fe420535124dbd85044840d
parent37a6387fa906e43115417c4a89069be043e2c554 (diff)
downloadchrome-ec-bff14cac0b17217a6be02924d109e58b3aaa50b1.tar.gz
i2c: Support command version numbers
Currently, I2C commands look like this: Input: cmd8 [params bytes] checksum Output: response8 [response_ptr bytes] checksum Use a prefix byte of (0xDC + cmd_version) to indicate the command version. This is compatible with the existing protocol, since there are no host commands in the range 0xDC-0xFB. If the first byte of the from-host data is 0x00-0xDB, it's a version 0 command. There is no change to the output format, since the EC needs to hand back a response which matches the version requested by the host. New input: (0xDC+ver8) cmd8 paramlen8 [params bytes] checksum New output: response8 responselen8 [response_ptr bytes] checksum If the host gets a response of EC_RES_INVALID_COMMAND, it knows it's talking to an old EC, and at most version 0 of the command is supported. BUG=chrome-os-partner:11317 TEST=manual and a bit ad-hoc: (note, this testing is not completed yet, so far only snow is tested) Check that snow and link still process commands correctly over I2C from U-Boot. SMDK5250 # mkbp test Old interface: New interface: Test passed Change-Id: I1c21f2b036091e9122b4f980ca5f5af34f7fc070 Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/27470
-rw-r--r--chip/stm32/i2c.c59
-rw-r--r--include/ec_commands.h12
-rw-r--r--include/host_command.h1
3 files changed, 57 insertions, 15 deletions
diff --git a/chip/stm32/i2c.c b/chip/stm32/i2c.c
index 31c5174c55..7e7bafefc6 100644
--- a/chip/stm32/i2c.c
+++ b/chip/stm32/i2c.c
@@ -41,8 +41,8 @@
static uint16_t i2c_sr1[NUM_PORTS];
static struct mutex i2c_mutex;
-/* buffer for host commands (including error code and checksum) */
-static uint8_t host_buffer[EC_HOST_PARAM_SIZE + 2];
+/* buffer for host commands (including version, error code and checksum) */
+static uint8_t host_buffer[EC_HOST_PARAM_SIZE + 4];
static struct host_cmd_handler_args host_cmd_args;
/* current position in host buffer for reception */
@@ -127,10 +127,14 @@ static void i2c_send_response(struct host_cmd_handler_args *args)
const uint8_t *data = args->response;
int size = args->response_size;
uint8_t *out = host_buffer;
- int sum, i;
+ int sum = 0, i;
*out++ = args->result;
- for (i = 0, sum = 0; i < size; i++, data++, out++) {
+ if (!args->i2c_old_response) {
+ *out++ = size;
+ sum = args->result + size;
+ }
+ for (i = 0; i < size; i++, data++, out++) {
if (data != out)
*out = *data;
sum += *data;
@@ -144,18 +148,43 @@ static void i2c_send_response(struct host_cmd_handler_args *args)
/* Process the command in the i2c host buffer */
static void i2c_process_command(void)
{
+ struct host_cmd_handler_args *args = &host_cmd_args;
+ char *buff = host_buffer;
+
+ args->command = *buff;
+ args->result = EC_RES_SUCCESS;
+ if (args->command >= EC_CMD_VERSION0) {
+ int csum, i;
+
+ /* Read version and data size */
+ args->version = args->command - EC_CMD_VERSION0;
+ args->command = buff[1];
+ args->params_size = buff[2];
+
+ /* Verify checksum */
+ for (csum = i = 0; i < args->params_size + 3; i++)
+ csum += buff[i];
+ if ((uint8_t)csum != buff[i])
+ args->result = EC_RES_INVALID_CHECKSUM;
+
+ buff += 3;
+ args->i2c_old_response = 0;
+ } else {
+ /* Old style command */
+ args->version = 0;
+ args->params_size = EC_HOST_PARAM_SIZE; /* unknown */
+ buff++;
+ args->i2c_old_response = 1;
+ }
+
/* we have an available command : execute it */
- host_cmd_args.command = host_buffer[0];
- host_cmd_args.result = EC_RES_SUCCESS;
- host_cmd_args.send_response = i2c_send_response;
- host_cmd_args.version = 0;
- host_cmd_args.params = host_buffer + 1;
- host_cmd_args.params_size = EC_HOST_PARAM_SIZE;
- /* skip room for error code */
- host_cmd_args.response = host_buffer + 1;
- host_cmd_args.response_max = EC_HOST_PARAM_SIZE;
- host_cmd_args.response_size = 0;
- host_command_received(&host_cmd_args);
+ args->send_response = i2c_send_response;
+ args->params = buff;
+ /* skip room for error code, arglen */
+ args->response = host_buffer + 2;
+ args->response_max = EC_HOST_PARAM_SIZE;
+ args->response_size = 0;
+ host_command_received(args);
}
static void i2c_event_handler(int port)
diff --git a/include/ec_commands.h b/include/ec_commands.h
index 6c64aeef1d..b102c0bd3c 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -926,6 +926,18 @@ struct ec_params_reboot_ec {
*/
#define EC_CMD_REBOOT 0xd1 /* Think "die" */
+/*
+ * This header byte on a command indicate version 0. Any header byte less
+ * than this means that we are talking to an old EC which doesn't support
+ * versioning. In that case, we assume version 0.
+ *
+ * Header bytes greater than this indicate a later version. For example,
+ * EC_CMD_VERSION0 + 1 means we are using version 1.
+ *
+ * The old EC interface must not use commands 0dc or higher.
+ */
+#define EC_CMD_VERSION0 0xdc
+
#endif /* !__ACPI__ */
#endif /* __CROS_EC_COMMANDS_H */
diff --git a/include/host_command.h b/include/host_command.h
index a88761a6e2..135f493737 100644
--- a/include/host_command.h
+++ b/include/host_command.h
@@ -22,6 +22,7 @@ struct host_cmd_handler_args {
uint8_t command; /* Command (e.g., EC_CMD_FLASH_GET_INFO) */
uint8_t version; /* Version of command (0-31) */
uint8_t params_size; /* Size of input parameters in bytes */
+ uint8_t i2c_old_response; /* (for I2C) send an old-style response */
const uint8_t *params; /* Input parameters */
/*
* Pointer to output response data buffer. On input to the handler,