diff options
Diffstat (limited to 'drivers/platform/chrome/wilco_ec')
-rw-r--r-- | drivers/platform/chrome/wilco_ec/Kconfig | 1 | ||||
-rw-r--r-- | drivers/platform/chrome/wilco_ec/debugfs.c | 89 | ||||
-rw-r--r-- | drivers/platform/chrome/wilco_ec/mailbox.c | 55 |
3 files changed, 78 insertions, 67 deletions
diff --git a/drivers/platform/chrome/wilco_ec/Kconfig b/drivers/platform/chrome/wilco_ec/Kconfig index e09e4cebe9b4..fd29cbfd3d5d 100644 --- a/drivers/platform/chrome/wilco_ec/Kconfig +++ b/drivers/platform/chrome/wilco_ec/Kconfig @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only config WILCO_EC tristate "ChromeOS Wilco Embedded Controller" depends on ACPI && X86 && CROS_EC_LPC && CROS_EC_LPC_MEC diff --git a/drivers/platform/chrome/wilco_ec/debugfs.c b/drivers/platform/chrome/wilco_ec/debugfs.c index c090db2cd5be..f163476d080d 100644 --- a/drivers/platform/chrome/wilco_ec/debugfs.c +++ b/drivers/platform/chrome/wilco_ec/debugfs.c @@ -4,31 +4,7 @@ * * Copyright 2019 Google LLC * - * There is only one attribute used for debugging, called raw. - * You can write a hexadecimal sentence to raw, and that series of bytes - * will be sent to the EC. Then, you can read the bytes of response - * by reading from raw. - * - * For writing: - * Bytes 0-1 indicate the message type: - * 00 F0 = Execute Legacy Command - * 00 F2 = Read/Write NVRAM Property - * Byte 2 provides the command code - * Bytes 3+ consist of the data passed in the request - * - * When referencing the EC interface spec, byte 2 corresponds to MBOX[0], - * byte 3 corresponds to MBOX[1], etc. - * - * At least three bytes are required, for the msg type and command, - * with additional bytes optional for additional data. - * - * Example: - * // Request EC info type 3 (EC firmware build date) - * $ echo 00 f0 38 00 03 00 > raw - * // View the result. The decoded ASCII result "12/21/18" is - * // included after the raw hex. - * $ cat raw - * 00 31 32 2f 32 31 2f 31 38 00 38 00 01 00 2f 00 .12/21/18.8... + * See Documentation/ABI/testing/debugfs-wilco-ec for usage. */ #include <linux/ctype.h> @@ -136,18 +112,15 @@ static ssize_t raw_write(struct file *file, const char __user *user_buf, ret = parse_hex_sentence(buf, kcount, request_data, TYPE_AND_DATA_SIZE); if (ret < 0) return ret; - /* Need at least two bytes for message type and one for command */ + /* Need at least two bytes for message type and one byte of data */ if (ret < 3) return -EINVAL; - /* Clear response data buffer */ - memset(debug_info->raw_data, '\0', EC_MAILBOX_DATA_SIZE_EXTENDED); - msg.type = request_data[0] << 8 | request_data[1]; - msg.flags = WILCO_EC_FLAG_RAW; - msg.command = request_data[2]; - msg.request_data = ret > 3 ? request_data + 3 : 0; - msg.request_size = ret - 3; + msg.flags = 0; + msg.request_data = request_data + 2; + msg.request_size = ret - 2; + memset(debug_info->raw_data, 0, sizeof(debug_info->raw_data)); msg.response_data = debug_info->raw_data; msg.response_size = EC_MAILBOX_DATA_SIZE; @@ -174,7 +147,8 @@ static ssize_t raw_read(struct file *file, char __user *user_buf, size_t count, fmt_len = hex_dump_to_buffer(debug_info->raw_data, debug_info->response_size, 16, 1, debug_info->formatted_data, - FORMATTED_BUFFER_SIZE, true); + sizeof(debug_info->formatted_data), + true); /* Only return response the first time it is read */ debug_info->response_size = 0; } @@ -190,6 +164,51 @@ static const struct file_operations fops_raw = { .llseek = no_llseek, }; +#define CMD_KB_CHROME 0x88 +#define SUB_CMD_H1_GPIO 0x0A + +struct h1_gpio_status_request { + u8 cmd; /* Always CMD_KB_CHROME */ + u8 reserved; + u8 sub_cmd; /* Always SUB_CMD_H1_GPIO */ +} __packed; + +struct hi_gpio_status_response { + u8 status; /* 0 if allowed */ + u8 val; /* BIT(0)=ENTRY_TO_FACT_MODE, BIT(1)=SPI_CHROME_SEL */ +} __packed; + +static int h1_gpio_get(void *arg, u64 *val) +{ + struct wilco_ec_device *ec = arg; + struct h1_gpio_status_request rq; + struct hi_gpio_status_response rs; + struct wilco_ec_message msg; + int ret; + + memset(&rq, 0, sizeof(rq)); + rq.cmd = CMD_KB_CHROME; + rq.sub_cmd = SUB_CMD_H1_GPIO; + + memset(&msg, 0, sizeof(msg)); + msg.type = WILCO_EC_MSG_LEGACY; + msg.request_data = &rq; + msg.request_size = sizeof(rq); + msg.response_data = &rs; + msg.response_size = sizeof(rs); + ret = wilco_ec_mailbox(ec, &msg); + if (ret < 0) + return ret; + if (rs.status) + return -EIO; + + *val = rs.val; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(fops_h1_gpio, h1_gpio_get, NULL, "0x%02llx\n"); + /** * wilco_ec_debugfs_probe() - Create the debugfs node * @pdev: The platform device, probably created in core.c @@ -211,6 +230,8 @@ static int wilco_ec_debugfs_probe(struct platform_device *pdev) if (!debug_info->dir) return 0; debugfs_create_file("raw", 0644, debug_info->dir, NULL, &fops_raw); + debugfs_create_file("h1_gpio", 0444, debug_info->dir, ec, + &fops_h1_gpio); return 0; } diff --git a/drivers/platform/chrome/wilco_ec/mailbox.c b/drivers/platform/chrome/wilco_ec/mailbox.c index f6ff29a11f1a..7fb58b487963 100644 --- a/drivers/platform/chrome/wilco_ec/mailbox.c +++ b/drivers/platform/chrome/wilco_ec/mailbox.c @@ -92,21 +92,10 @@ static void wilco_ec_prepare(struct wilco_ec_message *msg, struct wilco_ec_request *rq) { memset(rq, 0, sizeof(*rq)); - - /* Handle messages without trimming bytes from the request */ - if (msg->request_size && msg->flags & WILCO_EC_FLAG_RAW_REQUEST) { - rq->reserved_raw = *(u8 *)msg->request_data; - msg->request_size--; - memmove(msg->request_data, msg->request_data + 1, - msg->request_size); - } - - /* Fill in request packet */ rq->struct_version = EC_MAILBOX_PROTO_VERSION; rq->mailbox_id = msg->type; rq->mailbox_version = EC_MAILBOX_VERSION; - rq->data_size = msg->request_size + EC_MAILBOX_DATA_EXTRA; - rq->command = msg->command; + rq->data_size = msg->request_size; /* Checksum header and data */ rq->checksum = wilco_ec_checksum(rq, sizeof(*rq)); @@ -159,6 +148,12 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec, return -EIO; } + /* + * The EC always returns either EC_MAILBOX_DATA_SIZE or + * EC_MAILBOX_DATA_SIZE_EXTENDED bytes of data, so we need to + * calculate the checksum on **all** of this data, even if we + * won't use all of it. + */ if (msg->flags & WILCO_EC_FLAG_EXTENDED_DATA) size = EC_MAILBOX_DATA_SIZE_EXTENDED; else @@ -173,33 +168,26 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec, return -EBADMSG; } - /* Check that the EC reported success */ - msg->result = rs->result; - if (msg->result) { - dev_dbg(ec->dev, "bad response: 0x%02x\n", msg->result); + if (rs->result) { + dev_dbg(ec->dev, "EC reported failure: 0x%02x\n", rs->result); return -EBADMSG; } - /* Check the returned data size, skipping the header */ if (rs->data_size != size) { dev_dbg(ec->dev, "unexpected packet size (%u != %zu)", rs->data_size, size); return -EMSGSIZE; } - /* Skip 1 response data byte unless specified */ - size = (msg->flags & WILCO_EC_FLAG_RAW_RESPONSE) ? 0 : 1; - if ((ssize_t) rs->data_size - size < msg->response_size) { - dev_dbg(ec->dev, "response data too short (%zd < %zu)", - (ssize_t) rs->data_size - size, msg->response_size); + if (rs->data_size < msg->response_size) { + dev_dbg(ec->dev, "EC didn't return enough data (%u < %zu)", + rs->data_size, msg->response_size); return -EMSGSIZE; } - /* Ignore response data bytes as requested */ - memcpy(msg->response_data, rs->data + size, msg->response_size); + memcpy(msg->response_data, rs->data, msg->response_size); - /* Return actual amount of data received */ - return msg->response_size; + return rs->data_size; } /** @@ -207,10 +195,12 @@ static int wilco_ec_transfer(struct wilco_ec_device *ec, * @ec: EC device. * @msg: EC message data for request and response. * - * On entry msg->type, msg->flags, msg->command, msg->request_size, - * msg->response_size, and msg->request_data should all be filled in. + * On entry msg->type, msg->request_size, and msg->request_data should all be + * filled in. If desired, msg->flags can be set. * - * On exit msg->result and msg->response_data will be filled. + * If a response is expected, msg->response_size should be set, and + * msg->response_data should point to a buffer with enough space. On exit + * msg->response_data will be filled. * * Return: number of bytes received or negative error code on failure. */ @@ -219,15 +209,14 @@ int wilco_ec_mailbox(struct wilco_ec_device *ec, struct wilco_ec_message *msg) struct wilco_ec_request *rq; int ret; - dev_dbg(ec->dev, "cmd=%02x type=%04x flags=%02x rslen=%zu rqlen=%zu\n", - msg->command, msg->type, msg->flags, msg->response_size, - msg->request_size); + dev_dbg(ec->dev, "type=%04x flags=%02x rslen=%zu rqlen=%zu\n", + msg->type, msg->flags, msg->response_size, msg->request_size); + mutex_lock(&ec->mailbox_lock); /* Prepare request packet */ rq = ec->data_buffer; wilco_ec_prepare(msg, rq); - mutex_lock(&ec->mailbox_lock); ret = wilco_ec_transfer(ec, msg, rq); mutex_unlock(&ec->mailbox_lock); |