summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLouis Yung-Chieh Lo <yjlou@chromium.org>2012-05-29 18:03:42 +0800
committerLouis Yung-Chieh Lo <yjlou@chromium.org>2012-05-30 10:10:16 +0800
commit2835e5594e19d3de99fa4f77131908a13fd8a36d (patch)
tree8d41b97fec209dee05d46eb58c643a9681ca3a0b
parent8bb9091f2ec880f0f8b38559c0a8101ba46557a0 (diff)
downloadchrome-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>
-rw-r--r--util/comm-lpc.c38
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 */
}