summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2012-07-12 11:56:40 +0800
committerGerrit <chrome-bot@google.com>2012-07-12 02:35:21 -0700
commit0398874210b52d48c52ac95601a504fbf1b61e59 (patch)
tree0827d39155ab410f794d62645bd282b1edd2643a
parent54d14bf3fac5237e8c3b059c7019d6c7f88ee168 (diff)
downloadchrome-ec-0398874210b52d48c52ac95601a504fbf1b61e59.tar.gz
Add I2C read/write host command
These commands are only available when system is unlocked. BUG=chrome-os-partner:9716 TEST=When system is unlocked, check we can read/write I2C bus. When system is locked, check the commands return error. Change-Id: I8c4a8a42ab13d62c7e47bf33e2a7abc6f61e43fa Reviewed-on: https://gerrit.chromium.org/gerrit/27254 Reviewed-by: Rong Chang <rongchang@chromium.org> Commit-Ready: Vic Yang <victoryang@chromium.org> Tested-by: Vic Yang <victoryang@chromium.org>
-rw-r--r--common/build.mk1
-rw-r--r--common/i2c_commands.c55
-rw-r--r--include/ec_commands.h27
-rw-r--r--util/ectool.c108
4 files changed, 191 insertions, 0 deletions
diff --git a/common/build.mk b/common/build.mk
index bfdeb11058..f20e968933 100644
--- a/common/build.mk
+++ b/common/build.mk
@@ -14,6 +14,7 @@ common-$(CONFIG_CHARGER_BQ24725)+=charger_bq24725.o
common-$(CONFIG_PMU_TPS65090)+=pmu_tps65090.o pmu_tps65090_charger.o
common-$(CONFIG_EOPTION)+=eoption.o
common-$(CONFIG_FLASH)+=flash_common.o flash_commands.o fmap.o
+common-$(CONFIG_I2C)+=i2c_commands.o
common-$(CONFIG_IR357x)+=ir357x.o
common-$(CONFIG_LPC)+=port80.o
common-$(CONFIG_POWER_LED)+=power_led.o
diff --git a/common/i2c_commands.c b/common/i2c_commands.c
new file mode 100644
index 0000000000..6111b8ac7b
--- /dev/null
+++ b/common/i2c_commands.c
@@ -0,0 +1,55 @@
+/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* I2C host commands for Chrome EC */
+
+#include "host_command.h"
+#include "i2c.h"
+#include "system.h"
+
+int i2c_command_read(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_i2c_read *p =
+ (const struct ec_params_i2c_read *)args->params;
+ struct ec_response_i2c_read *r =
+ (struct ec_response_i2c_read *)args->response;
+ int data, rv = -1;
+
+ if (system_is_locked())
+ return EC_RES_ACCESS_DENIED;
+
+ if (p->read_size == 16)
+ rv = i2c_read16(p->port, p->addr, p->offset, &data);
+ else if (p->read_size == 8)
+ rv = i2c_read8(p->port, p->addr, p->offset, &data);
+
+ if (rv)
+ return EC_RES_ERROR;
+ r->data = data;
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_I2C_READ, i2c_command_read, EC_VER_MASK(0));
+
+int i2c_command_write(struct host_cmd_handler_args *args)
+{
+ const struct ec_params_i2c_write *p =
+ (const struct ec_params_i2c_write *)args->params;
+ int rv = -1;
+
+ if (system_is_locked())
+ return EC_RES_ACCESS_DENIED;
+
+ if (p->write_size == 16)
+ rv = i2c_write16(p->port, p->addr, p->offset, p->data);
+ else if (p->write_size == 8)
+ rv = i2c_write8(p->port, p->addr, p->offset, p->data);
+
+ if (rv)
+ return EC_RES_ERROR;
+
+ return EC_RES_SUCCESS;
+}
+DECLARE_HOST_COMMAND(EC_CMD_I2C_WRITE, i2c_command_write, EC_VER_MASK(0));
diff --git a/include/ec_commands.h b/include/ec_commands.h
index fb9bdc7d82..417e0a021a 100644
--- a/include/ec_commands.h
+++ b/include/ec_commands.h
@@ -741,6 +741,33 @@ struct ec_params_switch_enable_wireless {
} __packed;
/*****************************************************************************/
+/* I2C commands. Only available when flash write protect is unlocked. */
+
+/* Read I2C bus */
+#define EC_CMD_I2C_READ 0x94
+
+struct ec_params_i2c_read {
+ uint16_t addr;
+ uint8_t read_size; /* Either 8 or 16. */
+ uint8_t port;
+ uint8_t offset;
+} __packed;
+struct ec_response_i2c_read {
+ uint16_t data;
+} __packed;
+
+/* Write I2C bus */
+#define EC_CMD_I2C_WRITE 0x95
+
+struct ec_params_i2c_write {
+ uint16_t data;
+ uint16_t addr;
+ uint8_t write_size; /* Either 8 or 16. */
+ uint8_t port;
+ uint8_t offset;
+} __packed;
+
+/*****************************************************************************/
/* System commands */
/*
diff --git a/util/ectool.c b/util/ectool.c
index dc358ae8b9..9e3efec836 100644
--- a/util/ectool.c
+++ b/util/ectool.c
@@ -67,6 +67,10 @@ const char help_str[] =
" Checks for basic communication with EC\n"
" kbpress\n"
" Simulate key press\n"
+ " i2cread\n"
+ " Read I2C bus\n"
+ " i2cwrite\n"
+ " Write I2C bus\n"
" lightbar [CMDS]\n"
" Various lightbar control commands\n"
" pstoreinfo\n"
@@ -1471,6 +1475,108 @@ int cmd_wireless(int argc, char *argv[])
}
+int cmd_i2c_read(int argc, char *argv[])
+{
+ struct ec_params_i2c_read p;
+ struct ec_response_i2c_read r;
+ char *e;
+ int rv;
+
+ if (argc != 5) {
+ fprintf(stderr, "Usage: %s <8 | 16> <port> <addr> <offset>\n",
+ argv[0]);
+ return -1;
+ }
+
+ p.read_size = strtol(argv[1], &e, 0);
+ if ((e && *e) || (p.read_size != 8 && p.read_size != 16)) {
+ fprintf(stderr, "Bad read size.\n");
+ return -1;
+ }
+
+ p.port = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad port.\n");
+ return -1;
+ }
+
+ p.addr = strtol(argv[3], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad address.\n");
+ return -1;
+ }
+
+ p.offset = strtol(argv[4], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad offset.\n");
+ return -1;
+ }
+
+ rv = ec_command(EC_CMD_I2C_READ, &p, sizeof(p), &r, sizeof(r));
+
+ if (rv < 0)
+ return rv;
+
+ printf("Read from I2C port %d at 0x%x offset 0x%x = 0x%x\n",
+ p.port, p.addr, p.offset, r.data);
+ return 0;
+}
+
+
+int cmd_i2c_write(int argc, char *argv[])
+{
+ struct ec_params_i2c_write p;
+ char *e;
+ int rv;
+
+ if (argc != 6) {
+ fprintf(stderr,
+ "Usage: %s <8 | 16> <port> <addr> <offset> <data>\n",
+ argv[0]);
+ return -1;
+ }
+
+ p.write_size = strtol(argv[1], &e, 0);
+ if ((e && *e) || (p.write_size != 8 && p.write_size != 16)) {
+ fprintf(stderr, "Bad write size.\n");
+ return -1;
+ }
+
+ p.port = strtol(argv[2], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad port.\n");
+ return -1;
+ }
+
+ p.addr = strtol(argv[3], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad address.\n");
+ return -1;
+ }
+
+ p.offset = strtol(argv[4], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad offset.\n");
+ return -1;
+ }
+
+ p.data = strtol(argv[5], &e, 0);
+ if (e && *e) {
+ fprintf(stderr, "Bad data.\n");
+ return -1;
+ }
+
+ rv = ec_command(EC_CMD_I2C_WRITE, &p, sizeof(p), NULL, 0);
+
+ if (rv < 0)
+ return rv;
+
+ printf("Wrote 0x%x to I2C port %d at 0x%x offset 0x%x.\n",
+ p.data, p.port, p.addr, p.offset);
+ return 0;
+}
+
+
int cmd_lcd_backlight(int argc, char *argv[])
{
struct ec_params_switch_enable_backlight p;
@@ -1723,6 +1829,8 @@ const struct command commands[] = {
{"flashinfo", cmd_flash_info},
{"hello", cmd_hello},
{"kbpress", cmd_kbpress},
+ {"i2cread", cmd_i2c_read},
+ {"i2cwrite", cmd_i2c_write},
{"lightbar", cmd_lightbar},
{"vboot", cmd_vboot},
{"pstoreinfo", cmd_pstore_info},