summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic (Chun-Ju) Yang <victoryang@chromium.org>2014-01-16 16:09:42 +0800
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-01-17 18:12:53 +0000
commita32f1d5643d127a82f346aa52e963dac51b82abf (patch)
treeab96477ce76244faf80cb51020f009907c42a0ea
parent83d082a1f2173da5e087d3a853096cd9b720bc26 (diff)
downloadchrome-ec-a32f1d5643d127a82f346aa52e963dac51b82abf.tar.gz
mec1322: Speed up LPC transfer with auto-increment mode
The main bottleneck on current LPC transfer speed is the delay required between address write and data read/write. Using auto-increment mode, we can not only skip most of the delay but also skip repeated address write. This gives about 30x speed-up (comparing the time spent on 4096-byte read test.) BUG=chrome-os-partner:24107 TEST=Measure speed of 'ectool readtest' BRANCH=None Change-Id: Ib34661474b149b19a900c60db884bd474881f742 Signed-off-by: Vic (Chun-Ju) Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/182797 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--util/comm-mec1322.c91
1 files changed, 54 insertions, 37 deletions
diff --git a/util/comm-mec1322.c b/util/comm-mec1322.c
index dcbcb503bb..787626b433 100644
--- a/util/comm-mec1322.c
+++ b/util/comm-mec1322.c
@@ -47,24 +47,58 @@ static int wait_for_ec(int status_addr, int timeout_usec)
return -1; /* Timeout */
}
-static void write_memmap(uint8_t b, uint16_t addr)
+static inline void write_emi_address(uint16_t addr, int access_mode)
{
- addr -= 0x800;
- outb(addr & 0xfc, 0x82);
+ addr -= 0x800; /* EMI base is at 0x800 */
+ outb((addr & 0xfc) | (access_mode & 0x3), 0x82);
outb((addr >> 8) & 0x7f, 0x83);
usleep(500);
+}
+
+static void write_memmap(uint8_t b, uint16_t addr)
+{
+ write_emi_address(addr, 0);
outb(b, 0x84 + (addr & 0x3));
}
static uint8_t read_memmap(uint16_t addr)
{
- addr -= 0x800;
- outb(addr & 0xfc, 0x82);
- outb((addr >> 8) & 0x7f, 0x83);
- usleep(500);
+ write_emi_address(addr, 0);
return inb(0x84 + (addr & 0x3));
}
+static int burst_read(uint8_t *out, int *csum, uint16_t addr, int sz)
+{
+ int i;
+ if (addr & 0x3) /* Unaligned access unsupported */
+ return 1;
+ write_emi_address(addr, 3);
+ while (sz) {
+ for (i = 0; i < 4 && sz; ++i, --sz, ++out) {
+ *out = inb(0x84 + i);
+ if (csum)
+ *csum += *out;
+ }
+ }
+ return 0;
+}
+
+static int burst_write(const uint8_t *data, int *csum, uint16_t addr, int sz)
+{
+ int i;
+ if (addr & 0x3) /* Unaligned access unsupported */
+ return 1;
+ write_emi_address(addr, 3);
+ while (sz) {
+ for (i = 0; i < 4 && sz; ++i, --sz, ++data) {
+ outb(*data, 0x84 + i);
+ if (csum)
+ *csum += *data;
+ }
+ }
+ return 0;
+}
+
static void send_byte(uint8_t b, uint16_t addr)
{
if (addr >= 0x800 && addr <= 0x9ff)
@@ -86,8 +120,6 @@ static int ec_command_lpc(int command, int version,
void *indata, int insize)
{
struct ec_lpc_host_args args;
- const uint8_t *d;
- uint8_t *dout;
int csum;
int i;
@@ -100,15 +132,12 @@ static int ec_command_lpc(int command, int version,
csum = command + args.flags + args.command_version + args.data_size;
/* Write data and update checksum */
- for (i = 0, d = (uint8_t *)outdata; i < outsize; i++, d++) {
- send_byte(*d, EC_LPC_ADDR_HOST_PARAM + i);
- csum += *d;
- }
+ burst_write((uint8_t *)outdata, &csum, EC_LPC_ADDR_HOST_PARAM, outsize);
/* Finalize checksum and write args */
args.checksum = (uint8_t)csum;
- for (i = 0, d = (const uint8_t *)&args; i < sizeof(args); i++, d++)
- send_byte(*d, EC_LPC_ADDR_HOST_ARGS + i);
+ burst_write((const uint8_t *)&args, NULL,
+ EC_LPC_ADDR_HOST_ARGS, sizeof(args));
send_byte(command, EC_LPC_ADDR_HOST_CMD);
@@ -125,8 +154,7 @@ static int ec_command_lpc(int command, int version,
}
/* Read back args */
- for (i = 0, dout = (uint8_t *)&args; i < sizeof(args); i++, dout++)
- *dout = read_byte(EC_LPC_ADDR_HOST_ARGS + i);
+ burst_read((uint8_t *)&args, NULL, EC_LPC_ADDR_HOST_ARGS, sizeof(args));
/*
* If EC didn't modify args flags, then somehow we sent a new-style
@@ -147,11 +175,8 @@ static int ec_command_lpc(int command, int version,
csum = command + args.flags + args.command_version + args.data_size;
/* Read response and update checksum */
- for (i = 0, dout = (uint8_t *)indata; i < args.data_size;
- i++, dout++) {
- *dout = read_byte(EC_LPC_ADDR_HOST_PARAM + i);
- csum += *dout;
- }
+ burst_read((uint8_t *)indata, &csum,
+ EC_LPC_ADDR_HOST_PARAM, args.data_size);
/* Verify checksum */
if (args.checksum != (uint8_t)csum) {
@@ -170,7 +195,6 @@ static int ec_command_lpc_3(int command, int version,
struct ec_host_request rq;
struct ec_host_response rs;
const uint8_t *d;
- uint8_t *dout;
int csum = 0;
int i;
@@ -188,10 +212,8 @@ static int ec_command_lpc_3(int command, int version,
rq.data_len = outsize;
/* Copy data and start checksum */
- for (i = 0, d = (const uint8_t *)outdata; i < outsize; i++, d++) {
- send_byte(*d, EC_LPC_ADDR_HOST_PACKET + sizeof(rq) + i);
- csum += *d;
- }
+ burst_write((const uint8_t *)outdata, &csum,
+ EC_LPC_ADDR_HOST_PACKET + sizeof(rq), outsize);
/* Finish checksum */
for (i = 0, d = (const uint8_t *)&rq; i < sizeof(rq); i++, d++)
@@ -201,8 +223,8 @@ static int ec_command_lpc_3(int command, int version,
rq.checksum = (uint8_t)(-csum);
/* Copy header */
- for (i = 0, d = (const uint8_t *)&rq; i < sizeof(rq); i++, d++)
- send_byte(*d, EC_LPC_ADDR_HOST_PACKET + i);
+ burst_write((const uint8_t *)&rq, NULL,
+ EC_LPC_ADDR_HOST_PACKET, sizeof(rq));
/* Start the command */
send_byte(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD);
@@ -221,10 +243,7 @@ static int ec_command_lpc_3(int command, int version,
/* Read back response header and start checksum */
csum = 0;
- for (i = 0, dout = (uint8_t *)&rs; i < sizeof(rs); i++, dout++) {
- *dout = read_byte(EC_LPC_ADDR_HOST_PACKET + i);
- csum += *dout;
- }
+ burst_read((uint8_t *)&rs, &csum, EC_LPC_ADDR_HOST_PACKET, sizeof(rs));
if (rs.struct_version != EC_HOST_RESPONSE_VERSION) {
fprintf(stderr, "EC response version mismatch\n");
@@ -242,10 +261,8 @@ static int ec_command_lpc_3(int command, int version,
}
/* Read back data and update checksum */
- for (i = 0, dout = (uint8_t *)indata; i < rs.data_len; i++, dout++) {
- *dout = read_byte(EC_LPC_ADDR_HOST_PACKET + sizeof(rs) + i);
- csum += *dout;
- }
+ burst_read((uint8_t *)indata, &csum,
+ EC_LPC_ADDR_HOST_PACKET + sizeof(rs), rs.data_len);
/* Verify checksum */
if ((uint8_t)csum) {