From 4f332fbd4aeea3eb1cf2b7c8f103e3928430c9bd Mon Sep 17 00:00:00 2001 From: Shawn Nematbakhsh Date: Wed, 1 Apr 2015 15:49:57 -0700 Subject: [PATCH] chromeec: lpc: Read / write IO ports through common functions Rather than calling inb + outb directly, access the ports through common functions. This is in preparation for alternative access modes required by certain new embedded controllers. BUG=chrome-os-partner:38224 TEST=Manual on Samus. Verify system boots cleanly in normal mode. BRANCH=None Change-Id: I98783ff67a37d970019683bb589825bc5d68c033 Signed-off-by: Patrick Georgi Original-Commit-Id: 25afa3f95183d8cf2e9a35272c77e92fbc6ee030 Original-Change-Id: Ic9d8f7f5c5d392212e39db28ebceea461d46f796 Original-Signed-off-by: Shawn Nematbakhsh Original-Reviewed-on: https://chromium-review.googlesource.com/263571 Original-Reviewed-by: Duncan Laurie Reviewed-on: http://review.coreboot.org/9909 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/ec/google/chromeec/ec_lpc.c | 149 ++++++++++++++++++++------------ 1 file changed, 94 insertions(+), 55 deletions(-) diff --git a/src/ec/google/chromeec/ec_lpc.c b/src/ec/google/chromeec/ec_lpc.c index f5f5434548..0fa0cf8d6d 100644 --- a/src/ec/google/chromeec/ec_lpc.c +++ b/src/ec/google/chromeec/ec_lpc.c @@ -29,9 +29,63 @@ #include "ec.h" #include "ec_commands.h" +/* + * Read bytes from a given LPC-mapped address. + * + * @port: Base read address + * @length: Number of bytes to read + * @dest: Destination buffer + * @csum: Optional parameter, sums data read + */ +static void read_bytes(u16 port, unsigned int length, u8 *dest, u8 *csum) +{ + int i; + + for (i = 0; i < length; ++i) { + dest[i] = inb(port + i); + if (csum) + *csum += dest[i]; + } +} + +/* Read single byte and return byte read */ +static inline u8 read_byte(u16 port) +{ + u8 byte; + read_bytes(port, 1, &byte, NULL); + return byte; +} + +/* + * Write bytes to a given LPC-mapped address. + * + * @port: Base write address + * @length: Number of bytes to write + * @msg: Write data buffer + * @csum: Optional parameter, sums data written + */ +static void write_bytes(u16 port, unsigned int length, u8 *msg, u8 *csum) +{ + int i; + + for (i = 0; i < length; ++i) { + outb(msg[i], port + i); + if (csum) + *csum += msg[i]; + } +} + +/* Write single byte and return byte written */ +static inline u8 write_byte(u8 val, u16 port) +{ + u8 byte = val; + write_bytes(port, 1, &byte, NULL); + return byte; +} + static int google_chromeec_wait_ready(u16 port) { - u8 ec_status = inb(port); + u8 ec_status = read_byte(port); u32 time_count = 0; /* @@ -46,7 +100,7 @@ static int google_chromeec_wait_ready(u16 port) udelay(1); if (time_count++ == MAX_EC_TIMEOUT_US) return -1; - ec_status = inb(port); + ec_status = read_byte(port); } return 0; } @@ -61,7 +115,7 @@ static int read_memmap(u8 *data, u8 offset) } /* Issue the ACPI read command */ - outb(EC_CMD_ACPI_READ, EC_LPC_ADDR_ACPI_CMD); + write_byte(EC_CMD_ACPI_READ, EC_LPC_ADDR_ACPI_CMD); if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { printk(BIOS_ERR, "Timeout waiting for EC READ_EVENT!\n"); @@ -69,14 +123,14 @@ static int read_memmap(u8 *data, u8 offset) } /* Write data address */ - outb(offset + EC_ACPI_MEM_MAPPED_BEGIN, EC_LPC_ADDR_ACPI_DATA); + write_byte(offset + EC_ACPI_MEM_MAPPED_BEGIN, EC_LPC_ADDR_ACPI_DATA); if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { printk(BIOS_ERR, "Timeout waiting for EC DATA!\n"); return -1; } - *data = inb(EC_LPC_ADDR_ACPI_DATA); + *data = read_byte(EC_LPC_ADDR_ACPI_DATA); return 0; } #endif @@ -93,9 +147,9 @@ static int google_chromeec_command_version(void) return -1; } #else - id1 = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID); - id2 = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1); - flags = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS); + id1 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID); + id2 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1); + flags = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS); #endif if (id1 != 'E' || id2 != 'C') { @@ -119,8 +173,7 @@ static int google_chromeec_command_v3(struct chromeec_command *cec_command) struct ec_host_request rq; struct ec_host_response rs; const u8 *d; - u8 *dout; - int csum = 0; + u8 csum = 0; int i; if (cec_command->cmd_size_in + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) { @@ -151,25 +204,23 @@ static int google_chromeec_command_v3(struct chromeec_command *cec_command) rq.data_len = cec_command->cmd_size_in; /* Copy data and start checksum */ - for (i = 0, d = (const u8 *)cec_command->cmd_data_in; - i < cec_command->cmd_size_in; i++, d++) { - outb(*d, EC_LPC_ADDR_HOST_PACKET + sizeof(rq) + i); - csum += *d; - } + write_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rq), + cec_command->cmd_size_in, + (u8*)cec_command->cmd_data_in, + &csum); /* Finish checksum */ for (i = 0, d = (const u8 *)&rq; i < sizeof(rq); i++, d++) csum += *d; /* Write checksum field so the entire packet sums to 0 */ - rq.checksum = (u8)(-csum); + rq.checksum = -csum; /* Copy header */ - for (i = 0, d = (const uint8_t *)&rq; i < sizeof(rq); i++, d++) - outb(*d, EC_LPC_ADDR_HOST_PACKET + i); + write_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rq), (u8*)&rq, NULL); /* Start the command */ - outb(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD); + write_byte(EC_COMMAND_PROTOCOL_3, EC_LPC_ADDR_HOST_CMD); if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n", @@ -178,7 +229,7 @@ static int google_chromeec_command_v3(struct chromeec_command *cec_command) } /* Check result */ - cec_command->cmd_code = inb(EC_LPC_ADDR_HOST_DATA); + cec_command->cmd_code = read_byte(EC_LPC_ADDR_HOST_DATA); if (cec_command->cmd_code) { printk(BIOS_ERR, "EC returned error result code %d\n", cec_command->cmd_code); @@ -187,10 +238,7 @@ static int google_chromeec_command_v3(struct chromeec_command *cec_command) /* Read back response header and start checksum */ csum = 0; - for (i = 0, dout = (u8 *)&rs; i < sizeof(rs); i++, dout++) { - *dout = inb(EC_LPC_ADDR_HOST_PACKET + i); - csum += *dout; - } + read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rs), (u8*)&rs, &csum); if (rs.struct_version != EC_HOST_RESPONSE_VERSION) { printk(BIOS_ERR, "EC response version mismatch (%d != %d)\n", @@ -211,14 +259,13 @@ static int google_chromeec_command_v3(struct chromeec_command *cec_command) } /* Read back data and update checksum */ - for (i = 0, dout = (uint8_t *)cec_command->cmd_data_out; - i < rs.data_len; i++, dout++) { - *dout = inb(EC_LPC_ADDR_HOST_PACKET + sizeof(rs) + i); - csum += *dout; - } + read_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rs), + rs.data_len, + cec_command->cmd_data_out, + &csum); /* Verify checksum */ - if ((u8)csum) { + if (csum) { printk(BIOS_ERR, "EC response has invalid checksum\n"); return -1; } @@ -229,11 +276,8 @@ static int google_chromeec_command_v3(struct chromeec_command *cec_command) static int google_chromeec_command_v1(struct chromeec_command *cec_command) { struct ec_lpc_host_args args; - const u8 *d; - u8 *dout; u8 cmd_code = cec_command->cmd_code; - int csum; - int i; + u8 csum; /* Fill in args */ args.flags = EC_HOST_ARGS_FLAG_FROM_HOST; @@ -243,21 +287,18 @@ static int google_chromeec_command_v1(struct chromeec_command *cec_command) /* Initialize checksum */ csum = cmd_code + args.flags + args.command_version + args.data_size; - /* Write data and update checksum */ - for (i = 0, d = (const u8 *)cec_command->cmd_data_in; - i < cec_command->cmd_size_in; i++, d++) { - outb(*d, EC_LPC_ADDR_HOST_PARAM + i); - csum += *d; - } + write_bytes(EC_LPC_ADDR_HOST_PARAM, + cec_command->cmd_size_in, + (u8*)cec_command->cmd_data_in, + &csum); /* Finalize checksum and write args */ - args.checksum = (u8)csum; - for (i = 0, d = (const u8 *)&args; i < sizeof(args); i++, d++) - outb(*d, EC_LPC_ADDR_HOST_ARGS + i); + args.checksum = csum; + write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL); /* Issue the command */ - outb(cmd_code, EC_LPC_ADDR_HOST_CMD); + write_byte(cmd_code, EC_LPC_ADDR_HOST_CMD); if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) { printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n", @@ -266,13 +307,12 @@ static int google_chromeec_command_v1(struct chromeec_command *cec_command) } /* Check result */ - cec_command->cmd_code = inb(EC_LPC_ADDR_HOST_DATA); + cec_command->cmd_code = read_byte(EC_LPC_ADDR_HOST_DATA); if (cec_command->cmd_code) return 1; /* Read back args */ - for (i = 0, dout = (u8 *)&args; i < sizeof(args); i++, dout++) - *dout = inb(EC_LPC_ADDR_HOST_ARGS + i); + read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL); /* * If EC didn't modify args flags, then somehow we sent a new-style @@ -294,14 +334,13 @@ static int google_chromeec_command_v1(struct chromeec_command *cec_command) csum = cmd_code + args.flags + args.command_version + args.data_size; /* Read data, if any */ - for (i = 0, dout = (u8 *)cec_command->cmd_data_out; - i < args.data_size; i++, dout++) { - *dout = inb(EC_LPC_ADDR_HOST_PARAM + i); - csum += *dout; - } + read_bytes(EC_LPC_ADDR_HOST_PARAM, + args.data_size, + cec_command->cmd_data_out, + &csum); /* Verify checksum */ - if (args.checksum != (u8)csum) { + if (args.checksum != csum) { printk(BIOS_ERR, "EC response has invalid checksum\n"); return 1; } @@ -391,7 +430,7 @@ u8 google_chromeec_get_event(void) } /* Issue the ACPI query-event command */ - outb(EC_CMD_ACPI_QUERY_EVENT, EC_LPC_ADDR_ACPI_CMD); + write_byte(EC_CMD_ACPI_QUERY_EVENT, EC_LPC_ADDR_ACPI_CMD); if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) { printk(BIOS_ERR, "Timeout waiting for EC QUERY_EVENT!\n"); @@ -399,6 +438,6 @@ u8 google_chromeec_get_event(void) } /* Event (or 0 if none) is returned directly in the data byte */ - return inb(EC_LPC_ADDR_ACPI_DATA); + return read_byte(EC_LPC_ADDR_ACPI_DATA); } #endif