diff options
author | Vic Yang <victoryang@chromium.org> | 2012-07-12 11:56:40 +0800 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-07-12 02:35:21 -0700 |
commit | 0398874210b52d48c52ac95601a504fbf1b61e59 (patch) | |
tree | 0827d39155ab410f794d62645bd282b1edd2643a | |
parent | 54d14bf3fac5237e8c3b059c7019d6c7f88ee168 (diff) | |
download | chrome-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.mk | 1 | ||||
-rw-r--r-- | common/i2c_commands.c | 55 | ||||
-rw-r--r-- | include/ec_commands.h | 27 | ||||
-rw-r--r-- | util/ectool.c | 108 |
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}, |