cmd: cros_ec: Move crosec commands to cmd subdirectory
Move crosec commands from drivers/misc/cros_ec.c to cmd/cros_ec.c Acked-by: Simon Glass <sjg@chromium.org> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com> Cc: Simon Glass <sjg@chromium.org> Cc: Heiko Schocher <hs@denx.de> Cc: Bin Meng <bmeng.cn@gmail.com> Cc: Miao Yan <yanmiaobest@gmail.com> Cc: Masahiro Yamada <yamada.masahiro@socionext.com> Cc: Stefan Roese <sr@denx.de> Cc: Przemyslaw Marczak <p.marczak@samsung.com> Cc: Maxime Ripard <maxime.ripard@free-electrons.com> Cc: Nishanth Menon <nm@ti.com> Cc: u-boot@lists.denx.de
This commit is contained in:
parent
2f159402d9
commit
bfeba0173a
13
cmd/Kconfig
13
cmd/Kconfig
@ -677,6 +677,19 @@ config CMD_TPM_TEST
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Firmware commands"
|
||||
config CMD_CROS_EC
|
||||
bool "Enable crosec command"
|
||||
depends on CROS_EC
|
||||
default y
|
||||
help
|
||||
Enable command-line access to the Chrome OS EC (Embedded
|
||||
Controller). This provides the 'crosec' command which has
|
||||
a number of sub-commands for performing EC tasks such as
|
||||
updating its flash, accessing a small saved context area
|
||||
and talking to the I2C bus behind the EC (if there is one).
|
||||
endmenu
|
||||
|
||||
menu "Filesystem commands"
|
||||
config CMD_EXT2
|
||||
bool "ext2 command support"
|
||||
|
@ -128,6 +128,7 @@ obj-$(CONFIG_CMD_TRACE) += trace.o
|
||||
obj-$(CONFIG_HUSH_PARSER) += test.o
|
||||
obj-$(CONFIG_CMD_TPM) += tpm.o
|
||||
obj-$(CONFIG_CMD_TPM_TEST) += tpm_test.o
|
||||
obj-$(CONFIG_CMD_CROS_EC) += cros_ec.o
|
||||
obj-$(CONFIG_CMD_TSI148) += tsi148.o
|
||||
obj-$(CONFIG_CMD_UBI) += ubi.o
|
||||
obj-$(CONFIG_CMD_UBIFS) += ubifs.o
|
||||
|
365
cmd/cros_ec.c
Normal file
365
cmd/cros_ec.c
Normal file
@ -0,0 +1,365 @@
|
||||
/*
|
||||
* Chromium OS cros_ec driver
|
||||
*
|
||||
* Copyright (c) 2016 The Chromium OS Authors.
|
||||
* Copyright (c) 2016 National Instruments Corp
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <cros_ec.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
|
||||
/* Note: depends on enum ec_current_image */
|
||||
static const char * const ec_current_image_name[] = {"unknown", "RO", "RW"};
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/**
|
||||
* Perform a flash read or write command
|
||||
*
|
||||
* @param dev CROS-EC device to read/write
|
||||
* @param is_write 1 do to a write, 0 to do a read
|
||||
* @param argc Number of arguments
|
||||
* @param argv Arguments (2 is region, 3 is address)
|
||||
* @return 0 for ok, 1 for a usage error or -ve for ec command error
|
||||
* (negative EC_RES_...)
|
||||
*/
|
||||
static int do_read_write(struct cros_ec_dev *dev, int is_write, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
uint32_t offset, size = -1U, region_size;
|
||||
unsigned long addr;
|
||||
char *endp;
|
||||
int region;
|
||||
int ret;
|
||||
|
||||
region = cros_ec_decode_region(argc - 2, argv + 2);
|
||||
if (region == -1)
|
||||
return 1;
|
||||
if (argc < 4)
|
||||
return 1;
|
||||
addr = simple_strtoul(argv[3], &endp, 16);
|
||||
if (*argv[3] == 0 || *endp != 0)
|
||||
return 1;
|
||||
if (argc > 4) {
|
||||
size = simple_strtoul(argv[4], &endp, 16);
|
||||
if (*argv[4] == 0 || *endp != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = cros_ec_flash_offset(dev, region, &offset, ®ion_size);
|
||||
if (ret) {
|
||||
debug("%s: Could not read region info\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
if (size == -1U)
|
||||
size = region_size;
|
||||
|
||||
ret = is_write ?
|
||||
cros_ec_flash_write(dev, (uint8_t *)addr, offset, size) :
|
||||
cros_ec_flash_read(dev, (uint8_t *)addr, offset, size);
|
||||
if (ret) {
|
||||
debug("%s: Could not %s region\n", __func__,
|
||||
is_write ? "write" : "read");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct cros_ec_dev *dev;
|
||||
struct udevice *udev;
|
||||
const char *cmd;
|
||||
int ret = 0;
|
||||
|
||||
if (argc < 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
cmd = argv[1];
|
||||
if (0 == strcmp("init", cmd)) {
|
||||
/* Remove any existing device */
|
||||
ret = uclass_find_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (!ret)
|
||||
device_remove(udev);
|
||||
ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (ret) {
|
||||
printf("Could not init cros_ec device (err %d)\n", ret);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (ret) {
|
||||
printf("Cannot get cros-ec device (err=%d)\n", ret);
|
||||
return 1;
|
||||
}
|
||||
dev = dev_get_uclass_priv(udev);
|
||||
if (0 == strcmp("id", cmd)) {
|
||||
char id[MSG_BYTES];
|
||||
|
||||
if (cros_ec_read_id(dev, id, sizeof(id))) {
|
||||
debug("%s: Could not read KBC ID\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
printf("%s\n", id);
|
||||
} else if (0 == strcmp("info", cmd)) {
|
||||
struct ec_response_mkbp_info info;
|
||||
|
||||
if (cros_ec_info(dev, &info)) {
|
||||
debug("%s: Could not read KBC info\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
printf("rows = %u\n", info.rows);
|
||||
printf("cols = %u\n", info.cols);
|
||||
printf("switches = %#x\n", info.switches);
|
||||
} else if (0 == strcmp("curimage", cmd)) {
|
||||
enum ec_current_image image;
|
||||
|
||||
if (cros_ec_read_current_image(dev, &image)) {
|
||||
debug("%s: Could not read KBC image\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
printf("%d\n", image);
|
||||
} else if (0 == strcmp("hash", cmd)) {
|
||||
struct ec_response_vboot_hash hash;
|
||||
int i;
|
||||
|
||||
if (cros_ec_read_hash(dev, &hash)) {
|
||||
debug("%s: Could not read KBC hash\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (hash.hash_type == EC_VBOOT_HASH_TYPE_SHA256)
|
||||
printf("type: SHA-256\n");
|
||||
else
|
||||
printf("type: %d\n", hash.hash_type);
|
||||
|
||||
printf("offset: 0x%08x\n", hash.offset);
|
||||
printf("size: 0x%08x\n", hash.size);
|
||||
|
||||
printf("digest: ");
|
||||
for (i = 0; i < hash.digest_size; i++)
|
||||
printf("%02x", hash.hash_digest[i]);
|
||||
printf("\n");
|
||||
} else if (0 == strcmp("reboot", cmd)) {
|
||||
int region;
|
||||
enum ec_reboot_cmd cmd;
|
||||
|
||||
if (argc >= 3 && !strcmp(argv[2], "cold")) {
|
||||
cmd = EC_REBOOT_COLD;
|
||||
} else {
|
||||
region = cros_ec_decode_region(argc - 2, argv + 2);
|
||||
if (region == EC_FLASH_REGION_RO)
|
||||
cmd = EC_REBOOT_JUMP_RO;
|
||||
else if (region == EC_FLASH_REGION_RW)
|
||||
cmd = EC_REBOOT_JUMP_RW;
|
||||
else
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (cros_ec_reboot(dev, cmd, 0)) {
|
||||
debug("%s: Could not reboot KBC\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
} else if (0 == strcmp("events", cmd)) {
|
||||
uint32_t events;
|
||||
|
||||
if (cros_ec_get_host_events(dev, &events)) {
|
||||
debug("%s: Could not read host events\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
printf("0x%08x\n", events);
|
||||
} else if (0 == strcmp("clrevents", cmd)) {
|
||||
uint32_t events = 0x7fffffff;
|
||||
|
||||
if (argc >= 3)
|
||||
events = simple_strtol(argv[2], NULL, 0);
|
||||
|
||||
if (cros_ec_clear_host_events(dev, events)) {
|
||||
debug("%s: Could not clear host events\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
} else if (0 == strcmp("read", cmd)) {
|
||||
ret = do_read_write(dev, 0, argc, argv);
|
||||
if (ret > 0)
|
||||
return CMD_RET_USAGE;
|
||||
} else if (0 == strcmp("write", cmd)) {
|
||||
ret = do_read_write(dev, 1, argc, argv);
|
||||
if (ret > 0)
|
||||
return CMD_RET_USAGE;
|
||||
} else if (0 == strcmp("erase", cmd)) {
|
||||
int region = cros_ec_decode_region(argc - 2, argv + 2);
|
||||
uint32_t offset, size;
|
||||
|
||||
if (region == -1)
|
||||
return CMD_RET_USAGE;
|
||||
if (cros_ec_flash_offset(dev, region, &offset, &size)) {
|
||||
debug("%s: Could not read region info\n", __func__);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = cros_ec_flash_erase(dev, offset, size);
|
||||
if (ret) {
|
||||
debug("%s: Could not erase region\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
} else if (0 == strcmp("regioninfo", cmd)) {
|
||||
int region = cros_ec_decode_region(argc - 2, argv + 2);
|
||||
uint32_t offset, size;
|
||||
|
||||
if (region == -1)
|
||||
return CMD_RET_USAGE;
|
||||
ret = cros_ec_flash_offset(dev, region, &offset, &size);
|
||||
if (ret) {
|
||||
debug("%s: Could not read region info\n", __func__);
|
||||
} else {
|
||||
printf("Region: %s\n", region == EC_FLASH_REGION_RO ?
|
||||
"RO" : "RW");
|
||||
printf("Offset: %x\n", offset);
|
||||
printf("Size: %x\n", size);
|
||||
}
|
||||
} else if (0 == strcmp("flashinfo", cmd)) {
|
||||
struct ec_response_flash_info p;
|
||||
|
||||
ret = cros_ec_read_flashinfo(dev, &p);
|
||||
if (!ret) {
|
||||
printf("Flash size: %u\n", p.flash_size);
|
||||
printf("Write block size: %u\n", p.write_block_size);
|
||||
printf("Erase block size: %u\n", p.erase_block_size);
|
||||
}
|
||||
} else if (0 == strcmp("vbnvcontext", cmd)) {
|
||||
uint8_t block[EC_VBNV_BLOCK_SIZE];
|
||||
char buf[3];
|
||||
int i, len;
|
||||
unsigned long result;
|
||||
|
||||
if (argc <= 2) {
|
||||
ret = cros_ec_read_vbnvcontext(dev, block);
|
||||
if (!ret) {
|
||||
printf("vbnv_block: ");
|
||||
for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++)
|
||||
printf("%02x", block[i]);
|
||||
putc('\n');
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* TODO(clchiou): Move this to a utility function as
|
||||
* cmd_spi might want to call it.
|
||||
*/
|
||||
memset(block, 0, EC_VBNV_BLOCK_SIZE);
|
||||
len = strlen(argv[2]);
|
||||
buf[2] = '\0';
|
||||
for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++) {
|
||||
if (i * 2 >= len)
|
||||
break;
|
||||
buf[0] = argv[2][i * 2];
|
||||
if (i * 2 + 1 >= len)
|
||||
buf[1] = '0';
|
||||
else
|
||||
buf[1] = argv[2][i * 2 + 1];
|
||||
strict_strtoul(buf, 16, &result);
|
||||
block[i] = result;
|
||||
}
|
||||
ret = cros_ec_write_vbnvcontext(dev, block);
|
||||
}
|
||||
if (ret) {
|
||||
debug("%s: Could not %s VbNvContext\n", __func__,
|
||||
argc <= 2 ? "read" : "write");
|
||||
}
|
||||
} else if (0 == strcmp("test", cmd)) {
|
||||
int result = cros_ec_test(dev);
|
||||
|
||||
if (result)
|
||||
printf("Test failed with error %d\n", result);
|
||||
else
|
||||
puts("Test passed\n");
|
||||
} else if (0 == strcmp("version", cmd)) {
|
||||
struct ec_response_get_version *p;
|
||||
char *build_string;
|
||||
|
||||
ret = cros_ec_read_version(dev, &p);
|
||||
if (!ret) {
|
||||
/* Print versions */
|
||||
printf("RO version: %1.*s\n",
|
||||
(int)sizeof(p->version_string_ro),
|
||||
p->version_string_ro);
|
||||
printf("RW version: %1.*s\n",
|
||||
(int)sizeof(p->version_string_rw),
|
||||
p->version_string_rw);
|
||||
printf("Firmware copy: %s\n",
|
||||
(p->current_image <
|
||||
ARRAY_SIZE(ec_current_image_name) ?
|
||||
ec_current_image_name[p->current_image] :
|
||||
"?"));
|
||||
ret = cros_ec_read_build_info(dev, &build_string);
|
||||
if (!ret)
|
||||
printf("Build info: %s\n", build_string);
|
||||
}
|
||||
} else if (0 == strcmp("ldo", cmd)) {
|
||||
uint8_t index, state;
|
||||
char *endp;
|
||||
|
||||
if (argc < 3)
|
||||
return CMD_RET_USAGE;
|
||||
index = simple_strtoul(argv[2], &endp, 10);
|
||||
if (*argv[2] == 0 || *endp != 0)
|
||||
return CMD_RET_USAGE;
|
||||
if (argc > 3) {
|
||||
state = simple_strtoul(argv[3], &endp, 10);
|
||||
if (*argv[3] == 0 || *endp != 0)
|
||||
return CMD_RET_USAGE;
|
||||
ret = cros_ec_set_ldo(udev, index, state);
|
||||
} else {
|
||||
ret = cros_ec_get_ldo(udev, index, &state);
|
||||
if (!ret) {
|
||||
printf("LDO%d: %s\n", index,
|
||||
state == EC_LDO_STATE_ON ?
|
||||
"on" : "off");
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
debug("%s: Could not access LDO%d\n", __func__, index);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
printf("Error: CROS-EC command failed (error %d)\n", ret);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
crosec, 6, 1, do_cros_ec,
|
||||
"CROS-EC utility command",
|
||||
"init Re-init CROS-EC (done on startup automatically)\n"
|
||||
"crosec id Read CROS-EC ID\n"
|
||||
"crosec info Read CROS-EC info\n"
|
||||
"crosec curimage Read CROS-EC current image\n"
|
||||
"crosec hash Read CROS-EC hash\n"
|
||||
"crosec reboot [rw | ro | cold] Reboot CROS-EC\n"
|
||||
"crosec events Read CROS-EC host events\n"
|
||||
"crosec clrevents [mask] Clear CROS-EC host events\n"
|
||||
"crosec regioninfo <ro|rw> Read image info\n"
|
||||
"crosec flashinfo Read flash info\n"
|
||||
"crosec erase <ro|rw> Erase EC image\n"
|
||||
"crosec read <ro|rw> <addr> [<size>] Read EC image\n"
|
||||
"crosec write <ro|rw> <addr> [<size>] Write EC image\n"
|
||||
"crosec vbnvcontext [hexstring] Read [write] VbNvContext from EC\n"
|
||||
"crosec ldo <idx> [<state>] Switch/Read LDO state\n"
|
||||
"crosec test run tests on cros_ec\n"
|
||||
"crosec version Read CROS-EC version"
|
||||
);
|
@ -43,9 +43,6 @@ enum {
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/* Note: depends on enum ec_current_image */
|
||||
static const char * const ec_current_image_name[] = {"unknown", "RO", "RW"};
|
||||
|
||||
void cros_ec_dump_data(const char *name, int cmd, const uint8_t *data, int len)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -1164,354 +1161,6 @@ int cros_ec_i2c_tunnel(struct udevice *dev, int port, struct i2c_msg *in,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CMD_CROS_EC
|
||||
|
||||
/**
|
||||
* Perform a flash read or write command
|
||||
*
|
||||
* @param dev CROS-EC device to read/write
|
||||
* @param is_write 1 do to a write, 0 to do a read
|
||||
* @param argc Number of arguments
|
||||
* @param argv Arguments (2 is region, 3 is address)
|
||||
* @return 0 for ok, 1 for a usage error or -ve for ec command error
|
||||
* (negative EC_RES_...)
|
||||
*/
|
||||
static int do_read_write(struct cros_ec_dev *dev, int is_write, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
uint32_t offset, size = -1U, region_size;
|
||||
unsigned long addr;
|
||||
char *endp;
|
||||
int region;
|
||||
int ret;
|
||||
|
||||
region = cros_ec_decode_region(argc - 2, argv + 2);
|
||||
if (region == -1)
|
||||
return 1;
|
||||
if (argc < 4)
|
||||
return 1;
|
||||
addr = simple_strtoul(argv[3], &endp, 16);
|
||||
if (*argv[3] == 0 || *endp != 0)
|
||||
return 1;
|
||||
if (argc > 4) {
|
||||
size = simple_strtoul(argv[4], &endp, 16);
|
||||
if (*argv[4] == 0 || *endp != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = cros_ec_flash_offset(dev, region, &offset, ®ion_size);
|
||||
if (ret) {
|
||||
debug("%s: Could not read region info\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
if (size == -1U)
|
||||
size = region_size;
|
||||
|
||||
ret = is_write ?
|
||||
cros_ec_flash_write(dev, (uint8_t *)addr, offset, size) :
|
||||
cros_ec_flash_read(dev, (uint8_t *)addr, offset, size);
|
||||
if (ret) {
|
||||
debug("%s: Could not %s region\n", __func__,
|
||||
is_write ? "write" : "read");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_cros_ec(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct cros_ec_dev *dev;
|
||||
struct udevice *udev;
|
||||
const char *cmd;
|
||||
int ret = 0;
|
||||
|
||||
if (argc < 2)
|
||||
return CMD_RET_USAGE;
|
||||
|
||||
cmd = argv[1];
|
||||
if (0 == strcmp("init", cmd)) {
|
||||
/* Remove any existing device */
|
||||
ret = uclass_find_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (!ret)
|
||||
device_remove(udev);
|
||||
ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (ret) {
|
||||
printf("Could not init cros_ec device (err %d)\n", ret);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = uclass_get_device(UCLASS_CROS_EC, 0, &udev);
|
||||
if (ret) {
|
||||
printf("Cannot get cros-ec device (err=%d)\n", ret);
|
||||
return 1;
|
||||
}
|
||||
dev = dev_get_uclass_priv(udev);
|
||||
if (0 == strcmp("id", cmd)) {
|
||||
char id[MSG_BYTES];
|
||||
|
||||
if (cros_ec_read_id(dev, id, sizeof(id))) {
|
||||
debug("%s: Could not read KBC ID\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
printf("%s\n", id);
|
||||
} else if (0 == strcmp("info", cmd)) {
|
||||
struct ec_response_mkbp_info info;
|
||||
|
||||
if (cros_ec_info(dev, &info)) {
|
||||
debug("%s: Could not read KBC info\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
printf("rows = %u\n", info.rows);
|
||||
printf("cols = %u\n", info.cols);
|
||||
printf("switches = %#x\n", info.switches);
|
||||
} else if (0 == strcmp("curimage", cmd)) {
|
||||
enum ec_current_image image;
|
||||
|
||||
if (cros_ec_read_current_image(dev, &image)) {
|
||||
debug("%s: Could not read KBC image\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
printf("%d\n", image);
|
||||
} else if (0 == strcmp("hash", cmd)) {
|
||||
struct ec_response_vboot_hash hash;
|
||||
int i;
|
||||
|
||||
if (cros_ec_read_hash(dev, &hash)) {
|
||||
debug("%s: Could not read KBC hash\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (hash.hash_type == EC_VBOOT_HASH_TYPE_SHA256)
|
||||
printf("type: SHA-256\n");
|
||||
else
|
||||
printf("type: %d\n", hash.hash_type);
|
||||
|
||||
printf("offset: 0x%08x\n", hash.offset);
|
||||
printf("size: 0x%08x\n", hash.size);
|
||||
|
||||
printf("digest: ");
|
||||
for (i = 0; i < hash.digest_size; i++)
|
||||
printf("%02x", hash.hash_digest[i]);
|
||||
printf("\n");
|
||||
} else if (0 == strcmp("reboot", cmd)) {
|
||||
int region;
|
||||
enum ec_reboot_cmd cmd;
|
||||
|
||||
if (argc >= 3 && !strcmp(argv[2], "cold"))
|
||||
cmd = EC_REBOOT_COLD;
|
||||
else {
|
||||
region = cros_ec_decode_region(argc - 2, argv + 2);
|
||||
if (region == EC_FLASH_REGION_RO)
|
||||
cmd = EC_REBOOT_JUMP_RO;
|
||||
else if (region == EC_FLASH_REGION_RW)
|
||||
cmd = EC_REBOOT_JUMP_RW;
|
||||
else
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (cros_ec_reboot(dev, cmd, 0)) {
|
||||
debug("%s: Could not reboot KBC\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
} else if (0 == strcmp("events", cmd)) {
|
||||
uint32_t events;
|
||||
|
||||
if (cros_ec_get_host_events(dev, &events)) {
|
||||
debug("%s: Could not read host events\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
printf("0x%08x\n", events);
|
||||
} else if (0 == strcmp("clrevents", cmd)) {
|
||||
uint32_t events = 0x7fffffff;
|
||||
|
||||
if (argc >= 3)
|
||||
events = simple_strtol(argv[2], NULL, 0);
|
||||
|
||||
if (cros_ec_clear_host_events(dev, events)) {
|
||||
debug("%s: Could not clear host events\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
} else if (0 == strcmp("read", cmd)) {
|
||||
ret = do_read_write(dev, 0, argc, argv);
|
||||
if (ret > 0)
|
||||
return CMD_RET_USAGE;
|
||||
} else if (0 == strcmp("write", cmd)) {
|
||||
ret = do_read_write(dev, 1, argc, argv);
|
||||
if (ret > 0)
|
||||
return CMD_RET_USAGE;
|
||||
} else if (0 == strcmp("erase", cmd)) {
|
||||
int region = cros_ec_decode_region(argc - 2, argv + 2);
|
||||
uint32_t offset, size;
|
||||
|
||||
if (region == -1)
|
||||
return CMD_RET_USAGE;
|
||||
if (cros_ec_flash_offset(dev, region, &offset, &size)) {
|
||||
debug("%s: Could not read region info\n", __func__);
|
||||
ret = -1;
|
||||
} else {
|
||||
ret = cros_ec_flash_erase(dev, offset, size);
|
||||
if (ret) {
|
||||
debug("%s: Could not erase region\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
} else if (0 == strcmp("regioninfo", cmd)) {
|
||||
int region = cros_ec_decode_region(argc - 2, argv + 2);
|
||||
uint32_t offset, size;
|
||||
|
||||
if (region == -1)
|
||||
return CMD_RET_USAGE;
|
||||
ret = cros_ec_flash_offset(dev, region, &offset, &size);
|
||||
if (ret) {
|
||||
debug("%s: Could not read region info\n", __func__);
|
||||
} else {
|
||||
printf("Region: %s\n", region == EC_FLASH_REGION_RO ?
|
||||
"RO" : "RW");
|
||||
printf("Offset: %x\n", offset);
|
||||
printf("Size: %x\n", size);
|
||||
}
|
||||
} else if (0 == strcmp("flashinfo", cmd)) {
|
||||
struct ec_response_flash_info p;
|
||||
|
||||
ret = cros_ec_read_flashinfo(dev, &p);
|
||||
if (!ret) {
|
||||
printf("Flash size: %u\n", p.flash_size);
|
||||
printf("Write block size: %u\n", p.write_block_size);
|
||||
printf("Erase block size: %u\n", p.erase_block_size);
|
||||
}
|
||||
} else if (0 == strcmp("vbnvcontext", cmd)) {
|
||||
uint8_t block[EC_VBNV_BLOCK_SIZE];
|
||||
char buf[3];
|
||||
int i, len;
|
||||
unsigned long result;
|
||||
|
||||
if (argc <= 2) {
|
||||
ret = cros_ec_read_vbnvcontext(dev, block);
|
||||
if (!ret) {
|
||||
printf("vbnv_block: ");
|
||||
for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++)
|
||||
printf("%02x", block[i]);
|
||||
putc('\n');
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* TODO(clchiou): Move this to a utility function as
|
||||
* cmd_spi might want to call it.
|
||||
*/
|
||||
memset(block, 0, EC_VBNV_BLOCK_SIZE);
|
||||
len = strlen(argv[2]);
|
||||
buf[2] = '\0';
|
||||
for (i = 0; i < EC_VBNV_BLOCK_SIZE; i++) {
|
||||
if (i * 2 >= len)
|
||||
break;
|
||||
buf[0] = argv[2][i * 2];
|
||||
if (i * 2 + 1 >= len)
|
||||
buf[1] = '0';
|
||||
else
|
||||
buf[1] = argv[2][i * 2 + 1];
|
||||
strict_strtoul(buf, 16, &result);
|
||||
block[i] = result;
|
||||
}
|
||||
ret = cros_ec_write_vbnvcontext(dev, block);
|
||||
}
|
||||
if (ret) {
|
||||
debug("%s: Could not %s VbNvContext\n", __func__,
|
||||
argc <= 2 ? "read" : "write");
|
||||
}
|
||||
} else if (0 == strcmp("test", cmd)) {
|
||||
int result = cros_ec_test(dev);
|
||||
|
||||
if (result)
|
||||
printf("Test failed with error %d\n", result);
|
||||
else
|
||||
puts("Test passed\n");
|
||||
} else if (0 == strcmp("version", cmd)) {
|
||||
struct ec_response_get_version *p;
|
||||
char *build_string;
|
||||
|
||||
ret = cros_ec_read_version(dev, &p);
|
||||
if (!ret) {
|
||||
/* Print versions */
|
||||
printf("RO version: %1.*s\n",
|
||||
(int)sizeof(p->version_string_ro),
|
||||
p->version_string_ro);
|
||||
printf("RW version: %1.*s\n",
|
||||
(int)sizeof(p->version_string_rw),
|
||||
p->version_string_rw);
|
||||
printf("Firmware copy: %s\n",
|
||||
(p->current_image <
|
||||
ARRAY_SIZE(ec_current_image_name) ?
|
||||
ec_current_image_name[p->current_image] :
|
||||
"?"));
|
||||
ret = cros_ec_read_build_info(dev, &build_string);
|
||||
if (!ret)
|
||||
printf("Build info: %s\n", build_string);
|
||||
}
|
||||
} else if (0 == strcmp("ldo", cmd)) {
|
||||
uint8_t index, state;
|
||||
char *endp;
|
||||
|
||||
if (argc < 3)
|
||||
return CMD_RET_USAGE;
|
||||
index = simple_strtoul(argv[2], &endp, 10);
|
||||
if (*argv[2] == 0 || *endp != 0)
|
||||
return CMD_RET_USAGE;
|
||||
if (argc > 3) {
|
||||
state = simple_strtoul(argv[3], &endp, 10);
|
||||
if (*argv[3] == 0 || *endp != 0)
|
||||
return CMD_RET_USAGE;
|
||||
ret = cros_ec_set_ldo(udev, index, state);
|
||||
} else {
|
||||
ret = cros_ec_get_ldo(udev, index, &state);
|
||||
if (!ret) {
|
||||
printf("LDO%d: %s\n", index,
|
||||
state == EC_LDO_STATE_ON ?
|
||||
"on" : "off");
|
||||
}
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
debug("%s: Could not access LDO%d\n", __func__, index);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
return CMD_RET_USAGE;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
printf("Error: CROS-EC command failed (error %d)\n", ret);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
crosec, 6, 1, do_cros_ec,
|
||||
"CROS-EC utility command",
|
||||
"init Re-init CROS-EC (done on startup automatically)\n"
|
||||
"crosec id Read CROS-EC ID\n"
|
||||
"crosec info Read CROS-EC info\n"
|
||||
"crosec curimage Read CROS-EC current image\n"
|
||||
"crosec hash Read CROS-EC hash\n"
|
||||
"crosec reboot [rw | ro | cold] Reboot CROS-EC\n"
|
||||
"crosec events Read CROS-EC host events\n"
|
||||
"crosec clrevents [mask] Clear CROS-EC host events\n"
|
||||
"crosec regioninfo <ro|rw> Read image info\n"
|
||||
"crosec flashinfo Read flash info\n"
|
||||
"crosec erase <ro|rw> Erase EC image\n"
|
||||
"crosec read <ro|rw> <addr> [<size>] Read EC image\n"
|
||||
"crosec write <ro|rw> <addr> [<size>] Write EC image\n"
|
||||
"crosec vbnvcontext [hexstring] Read [write] VbNvContext from EC\n"
|
||||
"crosec ldo <idx> [<state>] Switch/Read LDO state\n"
|
||||
"crosec test run tests on cros_ec\n"
|
||||
"crosec version Read CROS-EC version"
|
||||
);
|
||||
#endif
|
||||
|
||||
UCLASS_DRIVER(cros_ec) = {
|
||||
.id = UCLASS_CROS_EC,
|
||||
.name = "cros_ec",
|
||||
|
@ -280,6 +280,17 @@ int cros_ec_flash_erase(struct cros_ec_dev *dev, uint32_t offset,
|
||||
int cros_ec_flash_read(struct cros_ec_dev *dev, uint8_t *data, uint32_t offset,
|
||||
uint32_t size);
|
||||
|
||||
/**
|
||||
* Read back flash parameters
|
||||
*
|
||||
* This function reads back parameters of the flash as reported by the EC
|
||||
*
|
||||
* @param dev Pointer to device
|
||||
* @param info Pointer to output flash info struct
|
||||
*/
|
||||
int cros_ec_read_flashinfo(struct cros_ec_dev *dev,
|
||||
struct ec_response_flash_info *info);
|
||||
|
||||
/**
|
||||
* Write data to the flash
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user