diff options
author | Louis Yung-Chieh Lo <yjlou@chromium.org> | 2012-05-29 18:03:42 +0800 |
---|---|---|
committer | Louis Yung-Chieh Lo <yjlou@chromium.org> | 2012-05-30 10:10:16 +0800 |
commit | 2835e5594e19d3de99fa4f77131908a13fd8a36d (patch) | |
tree | 8d41b97fec209dee05d46eb58c643a9681ca3a0b /util | |
parent | 8bb9091f2ec880f0f8b38559c0a8101ba46557a0 (diff) | |
download | chrome-ec-2835e5594e19d3de99fa4f77131908a13fd8a36d.tar.gz |
Improve the timeout when running on non-Google EC boards.
The udelay() has big overhead so that repeating calling leads big errors
(expect 1 sec of timeout, but actually 12 secs of timeout).
So, the improvement is to double the udelay count when BUSY bit is set.
Even better, if we can check the I/O port content before really running
the EC command, it can save more time.
BUG=chrome-os-partner:10003
TEST=tested on link, alex, zgb, lumpy, stumpy and mario.
Only mario takes 1 second to timeout.
Others stop when checking ports (takes around 0.01 second).
Change-Id: I96c6d8cbe6226d05428a2ab126815e934942f5a9
Signed-off-by: Louis Yung-Chieh Lo <yjlou@chromium.org>
Diffstat (limited to 'util')
-rw-r--r-- | util/comm-lpc.c | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/util/comm-lpc.c b/util/comm-lpc.c index 1eff85c4e1..8b42763753 100644 --- a/util/comm-lpc.c +++ b/util/comm-lpc.c @@ -6,19 +6,42 @@ #include <stdint.h> #include <stdio.h> #include <sys/io.h> +#include <sys/param.h> #include <unistd.h> #include "comm-host.h" #include "ec_commands.h" +#define INITIAL_UDELAY 10 /* 10 us */ +#define MAXIMUM_UDELAY 10000 /* 10 ms */ + int comm_init(void) { + int i; + int byte = 0xff; + /* Request I/O privilege */ if (iopl(3) < 0) { perror("Error getting I/O privilege"); return -3; } + + /* Test if the I/O port has been configured for GEC. + * If they all are 0xff, then very possible you cannot access GEC. */ + byte &= inb(EC_LPC_ADDR_USER_CMD); + byte &= inb(EC_LPC_ADDR_USER_DATA); + for (i = 0; i < EC_FLASH_SIZE_MAX /* big enough */; ++i) + byte &= inb(EC_LPC_ADDR_USER_PARAM + i); + if (byte == 0xff) { + fprintf(stderr, "Port 0x%x,0x%x,0x%x-0x%x are all 0xFF.\n", + EC_LPC_ADDR_USER_CMD, EC_LPC_ADDR_USER_DATA, + EC_LPC_ADDR_USER_PARAM, + EC_LPC_ADDR_USER_PARAM + EC_FLASH_SIZE_MAX - 1); + fprintf(stderr, "Very likely this board doesn't have GEC.\n"); + return -4; + } + return 0; } @@ -28,10 +51,21 @@ int comm_init(void) static int wait_for_ec(int status_addr, int timeout_usec) { int i; - for (i = 0; i < timeout_usec; i += 10) { - usleep(10); /* Delay first, in case we just sent a command */ + int delay = INITIAL_UDELAY; + + for (i = 0; i < timeout_usec; i += delay) { + /* Delay first, in case we just sent out a command but + * the EC hasn't raise the busy flag. However, I think + * this doesn't happen since the LPC commands are executed + * in order and the busy flag is set by hardware. + * TODO: move this delay after inb(status). */ + usleep(MIN(delay, timeout_usec - i)); + if (!(inb(status_addr) & EC_LPC_STATUS_BUSY_MASK)) return 0; + + /* Increase the delay interval */ + delay = MIN(delay * 2, MAXIMUM_UDELAY); } return -1; /* Timeout */ } |