diff options
author | Vic (Chun-Ju) Yang <victoryang@chromium.org> | 2014-01-16 16:09:42 +0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-01-17 18:12:53 +0000 |
commit | a32f1d5643d127a82f346aa52e963dac51b82abf (patch) | |
tree | ab96477ce76244faf80cb51020f009907c42a0ea | |
parent | 83d082a1f2173da5e087d3a853096cd9b720bc26 (diff) | |
download | chrome-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.c | 91 |
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) { |