Peter Marheine has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/63733 )
Change subject: ec/google/chromeec: allow custom command timeout ......................................................................
ec/google/chromeec: allow custom command timeout
EC flash erase commands can take longer than a second to complete on some devices (nearly five seconds was observed on Nereid). Allow commands to specify a custom timeout, and retain the current one second timeout if unspecified.
Several google_chromeec_command() callers are modified to ensure the timeout field is zero-initialized when the default should be used, and google_chromeec_flash_erase() has its timeout set to 10 seconds.
BUG=b:222987250 TEST=EC flash erase no longer times out on Nereid
Signed-off-by: Peter Marheine pmarheine@chromium.org Change-Id: I55d36479e680c34a8bff65776e7e295e94291342 --- M src/ec/google/chromeec/ec.c M src/ec/google/chromeec/ec.h M src/ec/google/chromeec/ec_lpc.c 3 files changed, 41 insertions(+), 33 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/33/63733/1
diff --git a/src/ec/google/chromeec/ec.c b/src/ec/google/chromeec/ec.c index 5d53926..eaeeaa2 100644 --- a/src/ec/google/chromeec/ec.c +++ b/src/ec/google/chromeec/ec.c @@ -598,6 +598,8 @@ .cmd_size_out = 0, .cmd_data_out = NULL, .cmd_dev_index = 0, + /* Some ECs are known to need multiple seconds to erase */ + .timeout_us = 10 * USECS_PER_SEC, };
if (google_chromeec_command(&cmd) != 0) @@ -608,15 +610,15 @@
int google_chromeec_flash_info(struct ec_response_flash_info *info) { - struct chromeec_command cmd; - - cmd.cmd_code = EC_CMD_FLASH_INFO; - cmd.cmd_version = 0; - cmd.cmd_size_in = 0; - cmd.cmd_data_in = NULL; - cmd.cmd_size_out = sizeof(*info); - cmd.cmd_data_out = info; - cmd.cmd_dev_index = 0; + struct chromeec_command cmd = { + .cmd_code = EC_CMD_FLASH_INFO, + .cmd_version = 0, + .cmd_size_in = 0, + .cmd_data_in = NULL, + .cmd_size_out = sizeof(*info), + .cmd_data_out = info, + .cmd_dev_index = 0, + };
if (google_chromeec_command(&cmd) != 0) return -1; @@ -1087,13 +1089,15 @@ msg->len = read_len; }
- cmd.cmd_code = EC_CMD_I2C_PASSTHRU; - cmd.cmd_version = 0; - cmd.cmd_data_in = p; - cmd.cmd_size_in = size + write_len; - cmd.cmd_data_out = r; - cmd.cmd_size_out = sizeof(*r) + read_len; - cmd.cmd_dev_index = 0; + cmd = (struct chromeec_command){ + .cmd_code = EC_CMD_I2C_PASSTHRU, + .cmd_version = 0, + .cmd_data_in = p, + .cmd_size_in = size + write_len, + .cmd_data_out = r, + .cmd_size_out = sizeof(*r) + read_len, + .cmd_dev_index = 0, + }; rv = google_chromeec_command(&cmd); if (rv != 0) return rv; diff --git a/src/ec/google/chromeec/ec.h b/src/ec/google/chromeec/ec.h index 131a460..37ea24a 100644 --- a/src/ec/google/chromeec/ec.h +++ b/src/ec/google/chromeec/ec.h @@ -154,6 +154,8 @@ uint16_t cmd_size_out; /* expected size of command response in, * actual received size out */ int cmd_dev_index;/* device index for passthru */ + uint32_t timeout_us; /* maximum time to wait for command completion + * or 0 for arbitrary default */ };
/* diff --git a/src/ec/google/chromeec/ec_lpc.c b/src/ec/google/chromeec/ec_lpc.c index a82ea5d..be801f6 100644 --- a/src/ec/google/chromeec/ec_lpc.c +++ b/src/ec/google/chromeec/ec_lpc.c @@ -91,15 +91,16 @@ return byte; }
-static int google_chromeec_status_check(u16 port, u8 mask, u8 cond) +static int google_chromeec_status_check(u16 port, u8 mask, u8 cond, u32 timeout_us) { struct stopwatch timeout_sw; - /* One second is more than plenty for any EC operation to complete */ - const uint64_t ec_status_timeout_us = 1 * USECS_PER_SEC; + /* One second is more than plenty for most EC operations to complete */ + if (timeout_us == 0) + timeout_us = 1 * USECS_PER_SEC; /* Wait 1 usec between read attempts */ const uint64_t ec_status_read_period_us = 1;
- stopwatch_init_usecs_expire(&timeout_sw, ec_status_timeout_us); + stopwatch_init_usecs_expire(&timeout_sw, timeout_us); do { if ((read_byte(port) & mask) == cond) return 0; @@ -108,18 +109,19 @@ return -1; }
-static int google_chromeec_wait_ready(u16 port) +static int google_chromeec_wait_ready(u16 port, u32 timeout_us) { return google_chromeec_status_check(port, EC_LPC_CMDR_PENDING | - EC_LPC_CMDR_BUSY, 0); + EC_LPC_CMDR_BUSY, 0, + timeout_us); }
#if CONFIG(EC_GOOGLE_CHROMEEC_ACPI_MEMMAP) /* Read memmap data through ACPI port 66/62 */ static int read_memmap(u8 *data, u8 offset) { - if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { + if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD, 0)) { printk(BIOS_ERR, "Timeout waiting for EC ready!\n"); return -1; } @@ -127,7 +129,7 @@ /* Issue the ACPI read command */ write_byte(EC_CMD_ACPI_READ, EC_LPC_ADDR_ACPI_CMD);
- if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { + if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD, 0)) { printk(BIOS_ERR, "Timeout waiting for EC READ_EVENT!\n"); return -1; } @@ -135,7 +137,7 @@ /* Write data address */ write_byte(offset + EC_ACPI_MEM_MAPPED_BEGIN, EC_LPC_ADDR_ACPI_DATA);
- if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { + if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD, 0)) { printk(BIOS_ERR, "Timeout waiting for EC DATA!\n"); return -1; } @@ -196,7 +198,7 @@ return -1; }
- if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { + if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD, 0)) { printk(BIOS_ERR, "Timeout waiting for EC start command %d!\n", cec_command->cmd_code); return -1; @@ -230,7 +232,7 @@ /* Start the command */ write_byte(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
- if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { + if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD, cec_command->timeout_us)) { printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n", cec_command->cmd_code); return -1; @@ -307,7 +309,7 @@ /* Issue the command */ write_byte(cmd_code, EC_LPC_ADDR_HOST_CMD);
- if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { + if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD, cec_command->timeout_us)) { printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n", cec_command->cmd_code); return 1; @@ -455,15 +457,15 @@ .enable_dev = enable_dev, };
-static int google_chromeec_data_ready(u16 port) +static int google_chromeec_data_ready(u16 port, u32 timeout_us) { return google_chromeec_status_check(port, EC_LPC_CMDR_DATA, - EC_LPC_CMDR_DATA); + EC_LPC_CMDR_DATA, timeout_us); }
enum host_event_code google_chromeec_get_event(void) { - if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { + if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD, 0)) { printk(BIOS_ERR, "Timeout waiting for EC ready!\n"); return EC_HOST_EVENT_NONE; } @@ -471,12 +473,12 @@ /* Issue the ACPI query-event command */ write_byte(EC_CMD_ACPI_QUERY_EVENT, EC_LPC_ADDR_ACPI_CMD);
- if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { + if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD, 0)) { printk(BIOS_ERR, "Timeout waiting for EC QUERY_EVENT!\n"); return EC_HOST_EVENT_NONE; }
- if (google_chromeec_data_ready(EC_LPC_ADDR_ACPI_CMD)) { + if (google_chromeec_data_ready(EC_LPC_ADDR_ACPI_CMD, 0)) { printk(BIOS_ERR, "Timeout waiting for data ready!\n"); return EC_HOST_EVENT_NONE; }