mirror of
https://github.com/fail0verflow/switch-coreboot.git
synced 2025-05-04 01:39:18 -04:00
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 <pgeorgi@chromium.org> Original-Commit-Id: 25afa3f95183d8cf2e9a35272c77e92fbc6ee030 Original-Change-Id: Ic9d8f7f5c5d392212e39db28ebceea461d46f796 Original-Signed-off-by: Shawn Nematbakhsh <shawnn@chromium.org> Original-Reviewed-on: https://chromium-review.googlesource.com/263571 Original-Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: http://review.coreboot.org/9909 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
parent
d9af30bec1
commit
4f332fbd4a
1 changed files with 94 additions and 55 deletions
|
@ -29,9 +29,63 @@
|
||||||
#include "ec.h"
|
#include "ec.h"
|
||||||
#include "ec_commands.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)
|
static int google_chromeec_wait_ready(u16 port)
|
||||||
{
|
{
|
||||||
u8 ec_status = inb(port);
|
u8 ec_status = read_byte(port);
|
||||||
u32 time_count = 0;
|
u32 time_count = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -46,7 +100,7 @@ static int google_chromeec_wait_ready(u16 port)
|
||||||
udelay(1);
|
udelay(1);
|
||||||
if (time_count++ == MAX_EC_TIMEOUT_US)
|
if (time_count++ == MAX_EC_TIMEOUT_US)
|
||||||
return -1;
|
return -1;
|
||||||
ec_status = inb(port);
|
ec_status = read_byte(port);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +115,7 @@ static int read_memmap(u8 *data, u8 offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Issue the ACPI read command */
|
/* 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)) {
|
if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
|
||||||
printk(BIOS_ERR, "Timeout waiting for EC READ_EVENT!\n");
|
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 */
|
/* 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)) {
|
if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
|
||||||
printk(BIOS_ERR, "Timeout waiting for EC DATA!\n");
|
printk(BIOS_ERR, "Timeout waiting for EC DATA!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*data = inb(EC_LPC_ADDR_ACPI_DATA);
|
*data = read_byte(EC_LPC_ADDR_ACPI_DATA);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -93,9 +147,9 @@ static int google_chromeec_command_version(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
id1 = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID);
|
id1 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID);
|
||||||
id2 = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1);
|
id2 = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID + 1);
|
||||||
flags = inb(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS);
|
flags = read_byte(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_HOST_CMD_FLAGS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (id1 != 'E' || id2 != 'C') {
|
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_request rq;
|
||||||
struct ec_host_response rs;
|
struct ec_host_response rs;
|
||||||
const u8 *d;
|
const u8 *d;
|
||||||
u8 *dout;
|
u8 csum = 0;
|
||||||
int csum = 0;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (cec_command->cmd_size_in + sizeof(rq) > EC_LPC_HOST_PACKET_SIZE) {
|
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;
|
rq.data_len = cec_command->cmd_size_in;
|
||||||
|
|
||||||
/* Copy data and start checksum */
|
/* Copy data and start checksum */
|
||||||
for (i = 0, d = (const u8 *)cec_command->cmd_data_in;
|
write_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rq),
|
||||||
i < cec_command->cmd_size_in; i++, d++) {
|
cec_command->cmd_size_in,
|
||||||
outb(*d, EC_LPC_ADDR_HOST_PACKET + sizeof(rq) + i);
|
(u8*)cec_command->cmd_data_in,
|
||||||
csum += *d;
|
&csum);
|
||||||
}
|
|
||||||
|
|
||||||
/* Finish checksum */
|
/* Finish checksum */
|
||||||
for (i = 0, d = (const u8 *)&rq; i < sizeof(rq); i++, d++)
|
for (i = 0, d = (const u8 *)&rq; i < sizeof(rq); i++, d++)
|
||||||
csum += *d;
|
csum += *d;
|
||||||
|
|
||||||
/* Write checksum field so the entire packet sums to 0 */
|
/* Write checksum field so the entire packet sums to 0 */
|
||||||
rq.checksum = (u8)(-csum);
|
rq.checksum = -csum;
|
||||||
|
|
||||||
/* Copy header */
|
/* Copy header */
|
||||||
for (i = 0, d = (const uint8_t *)&rq; i < sizeof(rq); i++, d++)
|
write_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rq), (u8*)&rq, NULL);
|
||||||
outb(*d, EC_LPC_ADDR_HOST_PACKET + i);
|
|
||||||
|
|
||||||
/* Start the command */
|
/* 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)) {
|
if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
|
||||||
printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n",
|
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 */
|
/* 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) {
|
if (cec_command->cmd_code) {
|
||||||
printk(BIOS_ERR, "EC returned error result code %d\n",
|
printk(BIOS_ERR, "EC returned error result code %d\n",
|
||||||
cec_command->cmd_code);
|
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 */
|
/* Read back response header and start checksum */
|
||||||
csum = 0;
|
csum = 0;
|
||||||
for (i = 0, dout = (u8 *)&rs; i < sizeof(rs); i++, dout++) {
|
read_bytes(EC_LPC_ADDR_HOST_PACKET, sizeof(rs), (u8*)&rs, &csum);
|
||||||
*dout = inb(EC_LPC_ADDR_HOST_PACKET + i);
|
|
||||||
csum += *dout;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rs.struct_version != EC_HOST_RESPONSE_VERSION) {
|
if (rs.struct_version != EC_HOST_RESPONSE_VERSION) {
|
||||||
printk(BIOS_ERR, "EC response version mismatch (%d != %d)\n",
|
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 */
|
/* Read back data and update checksum */
|
||||||
for (i = 0, dout = (uint8_t *)cec_command->cmd_data_out;
|
read_bytes(EC_LPC_ADDR_HOST_PACKET + sizeof(rs),
|
||||||
i < rs.data_len; i++, dout++) {
|
rs.data_len,
|
||||||
*dout = inb(EC_LPC_ADDR_HOST_PACKET + sizeof(rs) + i);
|
cec_command->cmd_data_out,
|
||||||
csum += *dout;
|
&csum);
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify checksum */
|
/* Verify checksum */
|
||||||
if ((u8)csum) {
|
if (csum) {
|
||||||
printk(BIOS_ERR, "EC response has invalid checksum\n");
|
printk(BIOS_ERR, "EC response has invalid checksum\n");
|
||||||
return -1;
|
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)
|
static int google_chromeec_command_v1(struct chromeec_command *cec_command)
|
||||||
{
|
{
|
||||||
struct ec_lpc_host_args args;
|
struct ec_lpc_host_args args;
|
||||||
const u8 *d;
|
|
||||||
u8 *dout;
|
|
||||||
u8 cmd_code = cec_command->cmd_code;
|
u8 cmd_code = cec_command->cmd_code;
|
||||||
int csum;
|
u8 csum;
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Fill in args */
|
/* Fill in args */
|
||||||
args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
|
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 */
|
/* Initialize checksum */
|
||||||
csum = cmd_code + args.flags + args.command_version + args.data_size;
|
csum = cmd_code + args.flags + args.command_version + args.data_size;
|
||||||
|
|
||||||
/* Write data and update checksum */
|
write_bytes(EC_LPC_ADDR_HOST_PARAM,
|
||||||
for (i = 0, d = (const u8 *)cec_command->cmd_data_in;
|
cec_command->cmd_size_in,
|
||||||
i < cec_command->cmd_size_in; i++, d++) {
|
(u8*)cec_command->cmd_data_in,
|
||||||
outb(*d, EC_LPC_ADDR_HOST_PARAM + i);
|
&csum);
|
||||||
csum += *d;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Finalize checksum and write args */
|
/* Finalize checksum and write args */
|
||||||
args.checksum = (u8)csum;
|
args.checksum = csum;
|
||||||
for (i = 0, d = (const u8 *)&args; i < sizeof(args); i++, d++)
|
write_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL);
|
||||||
outb(*d, EC_LPC_ADDR_HOST_ARGS + i);
|
|
||||||
|
|
||||||
|
|
||||||
/* Issue the command */
|
/* 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)) {
|
if (google_chromeec_wait_ready(EC_LPC_ADDR_HOST_CMD)) {
|
||||||
printk(BIOS_ERR, "Timeout waiting for EC process command %d!\n",
|
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 */
|
/* 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)
|
if (cec_command->cmd_code)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* Read back args */
|
/* Read back args */
|
||||||
for (i = 0, dout = (u8 *)&args; i < sizeof(args); i++, dout++)
|
read_bytes(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8*)&args, NULL);
|
||||||
*dout = inb(EC_LPC_ADDR_HOST_ARGS + i);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If EC didn't modify args flags, then somehow we sent a new-style
|
* 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;
|
csum = cmd_code + args.flags + args.command_version + args.data_size;
|
||||||
|
|
||||||
/* Read data, if any */
|
/* Read data, if any */
|
||||||
for (i = 0, dout = (u8 *)cec_command->cmd_data_out;
|
read_bytes(EC_LPC_ADDR_HOST_PARAM,
|
||||||
i < args.data_size; i++, dout++) {
|
args.data_size,
|
||||||
*dout = inb(EC_LPC_ADDR_HOST_PARAM + i);
|
cec_command->cmd_data_out,
|
||||||
csum += *dout;
|
&csum);
|
||||||
}
|
|
||||||
|
|
||||||
/* Verify checksum */
|
/* Verify checksum */
|
||||||
if (args.checksum != (u8)csum) {
|
if (args.checksum != csum) {
|
||||||
printk(BIOS_ERR, "EC response has invalid checksum\n");
|
printk(BIOS_ERR, "EC response has invalid checksum\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -391,7 +430,7 @@ u8 google_chromeec_get_event(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Issue the ACPI query-event command */
|
/* 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)) {
|
if (google_chromeec_wait_ready(EC_LPC_ADDR_ACPI_CMD)) {
|
||||||
printk(BIOS_ERR, "Timeout waiting for EC QUERY_EVENT!\n");
|
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 */
|
/* 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
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue