cros_ec_proto.c (26684B)
1// SPDX-License-Identifier: GPL-2.0 2// ChromeOS EC communication protocol helper functions 3// 4// Copyright (C) 2015 Google, Inc 5 6#include <linux/delay.h> 7#include <linux/device.h> 8#include <linux/module.h> 9#include <linux/platform_data/cros_ec_commands.h> 10#include <linux/platform_data/cros_ec_proto.h> 11#include <linux/slab.h> 12#include <asm/unaligned.h> 13 14#include "cros_ec_trace.h" 15 16#define EC_COMMAND_RETRIES 50 17 18static const int cros_ec_error_map[] = { 19 [EC_RES_INVALID_COMMAND] = -EOPNOTSUPP, 20 [EC_RES_ERROR] = -EIO, 21 [EC_RES_INVALID_PARAM] = -EINVAL, 22 [EC_RES_ACCESS_DENIED] = -EACCES, 23 [EC_RES_INVALID_RESPONSE] = -EPROTO, 24 [EC_RES_INVALID_VERSION] = -ENOPROTOOPT, 25 [EC_RES_INVALID_CHECKSUM] = -EBADMSG, 26 [EC_RES_IN_PROGRESS] = -EINPROGRESS, 27 [EC_RES_UNAVAILABLE] = -ENODATA, 28 [EC_RES_TIMEOUT] = -ETIMEDOUT, 29 [EC_RES_OVERFLOW] = -EOVERFLOW, 30 [EC_RES_INVALID_HEADER] = -EBADR, 31 [EC_RES_REQUEST_TRUNCATED] = -EBADR, 32 [EC_RES_RESPONSE_TOO_BIG] = -EFBIG, 33 [EC_RES_BUS_ERROR] = -EFAULT, 34 [EC_RES_BUSY] = -EBUSY, 35 [EC_RES_INVALID_HEADER_VERSION] = -EBADMSG, 36 [EC_RES_INVALID_HEADER_CRC] = -EBADMSG, 37 [EC_RES_INVALID_DATA_CRC] = -EBADMSG, 38 [EC_RES_DUP_UNAVAILABLE] = -ENODATA, 39}; 40 41static int cros_ec_map_error(uint32_t result) 42{ 43 int ret = 0; 44 45 if (result != EC_RES_SUCCESS) { 46 if (result < ARRAY_SIZE(cros_ec_error_map) && cros_ec_error_map[result]) 47 ret = cros_ec_error_map[result]; 48 else 49 ret = -EPROTO; 50 } 51 52 return ret; 53} 54 55static int prepare_packet(struct cros_ec_device *ec_dev, 56 struct cros_ec_command *msg) 57{ 58 struct ec_host_request *request; 59 u8 *out; 60 int i; 61 u8 csum = 0; 62 63 if (msg->outsize + sizeof(*request) > ec_dev->dout_size) 64 return -EINVAL; 65 66 out = ec_dev->dout; 67 request = (struct ec_host_request *)out; 68 request->struct_version = EC_HOST_REQUEST_VERSION; 69 request->checksum = 0; 70 request->command = msg->command; 71 request->command_version = msg->version; 72 request->reserved = 0; 73 request->data_len = msg->outsize; 74 75 for (i = 0; i < sizeof(*request); i++) 76 csum += out[i]; 77 78 /* Copy data and update checksum */ 79 memcpy(out + sizeof(*request), msg->data, msg->outsize); 80 for (i = 0; i < msg->outsize; i++) 81 csum += msg->data[i]; 82 83 request->checksum = -csum; 84 85 return sizeof(*request) + msg->outsize; 86} 87 88static int send_command(struct cros_ec_device *ec_dev, 89 struct cros_ec_command *msg) 90{ 91 int ret; 92 int (*xfer_fxn)(struct cros_ec_device *ec, struct cros_ec_command *msg); 93 94 if (ec_dev->proto_version > 2) 95 xfer_fxn = ec_dev->pkt_xfer; 96 else 97 xfer_fxn = ec_dev->cmd_xfer; 98 99 if (!xfer_fxn) { 100 /* 101 * This error can happen if a communication error happened and 102 * the EC is trying to use protocol v2, on an underlying 103 * communication mechanism that does not support v2. 104 */ 105 dev_err_once(ec_dev->dev, 106 "missing EC transfer API, cannot send command\n"); 107 return -EIO; 108 } 109 110 trace_cros_ec_request_start(msg); 111 ret = (*xfer_fxn)(ec_dev, msg); 112 trace_cros_ec_request_done(msg, ret); 113 if (msg->result == EC_RES_IN_PROGRESS) { 114 int i; 115 struct cros_ec_command *status_msg; 116 struct ec_response_get_comms_status *status; 117 118 status_msg = kmalloc(sizeof(*status_msg) + sizeof(*status), 119 GFP_KERNEL); 120 if (!status_msg) 121 return -ENOMEM; 122 123 status_msg->version = 0; 124 status_msg->command = EC_CMD_GET_COMMS_STATUS; 125 status_msg->insize = sizeof(*status); 126 status_msg->outsize = 0; 127 128 /* 129 * Query the EC's status until it's no longer busy or 130 * we encounter an error. 131 */ 132 for (i = 0; i < EC_COMMAND_RETRIES; i++) { 133 usleep_range(10000, 11000); 134 135 trace_cros_ec_request_start(status_msg); 136 ret = (*xfer_fxn)(ec_dev, status_msg); 137 trace_cros_ec_request_done(status_msg, ret); 138 if (ret == -EAGAIN) 139 continue; 140 if (ret < 0) 141 break; 142 143 msg->result = status_msg->result; 144 if (status_msg->result != EC_RES_SUCCESS) 145 break; 146 147 status = (struct ec_response_get_comms_status *) 148 status_msg->data; 149 if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) 150 break; 151 } 152 153 kfree(status_msg); 154 } 155 156 return ret; 157} 158 159/** 160 * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer. 161 * @ec_dev: Device to register. 162 * @msg: Message to write. 163 * 164 * This is intended to be used by all ChromeOS EC drivers, but at present 165 * only SPI uses it. Once LPC uses the same protocol it can start using it. 166 * I2C could use it now, with a refactor of the existing code. 167 * 168 * Return: number of prepared bytes on success or negative error code. 169 */ 170int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, 171 struct cros_ec_command *msg) 172{ 173 u8 *out; 174 u8 csum; 175 int i; 176 177 if (ec_dev->proto_version > 2) 178 return prepare_packet(ec_dev, msg); 179 180 if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE) 181 return -EINVAL; 182 183 out = ec_dev->dout; 184 out[0] = EC_CMD_VERSION0 + msg->version; 185 out[1] = msg->command; 186 out[2] = msg->outsize; 187 csum = out[0] + out[1] + out[2]; 188 for (i = 0; i < msg->outsize; i++) 189 csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->data[i]; 190 out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = csum; 191 192 return EC_MSG_TX_PROTO_BYTES + msg->outsize; 193} 194EXPORT_SYMBOL(cros_ec_prepare_tx); 195 196/** 197 * cros_ec_check_result() - Check ec_msg->result. 198 * @ec_dev: EC device. 199 * @msg: Message to check. 200 * 201 * This is used by ChromeOS EC drivers to check the ec_msg->result for 202 * errors and to warn about them. 203 * 204 * Return: 0 on success or negative error code. 205 */ 206int cros_ec_check_result(struct cros_ec_device *ec_dev, 207 struct cros_ec_command *msg) 208{ 209 switch (msg->result) { 210 case EC_RES_SUCCESS: 211 return 0; 212 case EC_RES_IN_PROGRESS: 213 dev_dbg(ec_dev->dev, "command 0x%02x in progress\n", 214 msg->command); 215 return -EAGAIN; 216 default: 217 dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n", 218 msg->command, msg->result); 219 return 0; 220 } 221} 222EXPORT_SYMBOL(cros_ec_check_result); 223 224/* 225 * cros_ec_get_host_event_wake_mask 226 * 227 * Get the mask of host events that cause wake from suspend. 228 * 229 * @ec_dev: EC device to call 230 * @msg: message structure to use 231 * @mask: result when function returns >=0. 232 * 233 * LOCKING: 234 * the caller has ec_dev->lock mutex, or the caller knows there is 235 * no other command in progress. 236 */ 237static int cros_ec_get_host_event_wake_mask(struct cros_ec_device *ec_dev, 238 struct cros_ec_command *msg, 239 uint32_t *mask) 240{ 241 struct ec_response_host_event_mask *r; 242 int ret; 243 244 msg->command = EC_CMD_HOST_EVENT_GET_WAKE_MASK; 245 msg->version = 0; 246 msg->outsize = 0; 247 msg->insize = sizeof(*r); 248 249 ret = send_command(ec_dev, msg); 250 if (ret >= 0) { 251 if (msg->result == EC_RES_INVALID_COMMAND) 252 return -EOPNOTSUPP; 253 if (msg->result != EC_RES_SUCCESS) 254 return -EPROTO; 255 } 256 if (ret > 0) { 257 r = (struct ec_response_host_event_mask *)msg->data; 258 *mask = r->mask; 259 } 260 261 return ret; 262} 263 264static int cros_ec_host_command_proto_query(struct cros_ec_device *ec_dev, 265 int devidx, 266 struct cros_ec_command *msg) 267{ 268 /* 269 * Try using v3+ to query for supported protocols. If this 270 * command fails, fall back to v2. Returns the highest protocol 271 * supported by the EC. 272 * Also sets the max request/response/passthru size. 273 */ 274 int ret; 275 276 if (!ec_dev->pkt_xfer) 277 return -EPROTONOSUPPORT; 278 279 memset(msg, 0, sizeof(*msg)); 280 msg->command = EC_CMD_PASSTHRU_OFFSET(devidx) | EC_CMD_GET_PROTOCOL_INFO; 281 msg->insize = sizeof(struct ec_response_get_protocol_info); 282 283 ret = send_command(ec_dev, msg); 284 /* 285 * Send command once again when timeout occurred. 286 * Fingerprint MCU (FPMCU) is restarted during system boot which 287 * introduces small window in which FPMCU won't respond for any 288 * messages sent by kernel. There is no need to wait before next 289 * attempt because we waited at least EC_MSG_DEADLINE_MS. 290 */ 291 if (ret == -ETIMEDOUT) 292 ret = send_command(ec_dev, msg); 293 294 if (ret < 0) { 295 dev_dbg(ec_dev->dev, 296 "failed to check for EC[%d] protocol version: %d\n", 297 devidx, ret); 298 return ret; 299 } 300 301 if (devidx > 0 && msg->result == EC_RES_INVALID_COMMAND) 302 return -ENODEV; 303 else if (msg->result != EC_RES_SUCCESS) 304 return msg->result; 305 306 return 0; 307} 308 309static int cros_ec_host_command_proto_query_v2(struct cros_ec_device *ec_dev) 310{ 311 struct cros_ec_command *msg; 312 struct ec_params_hello *hello_params; 313 struct ec_response_hello *hello_response; 314 int ret; 315 int len = max(sizeof(*hello_params), sizeof(*hello_response)); 316 317 msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL); 318 if (!msg) 319 return -ENOMEM; 320 321 msg->version = 0; 322 msg->command = EC_CMD_HELLO; 323 hello_params = (struct ec_params_hello *)msg->data; 324 msg->outsize = sizeof(*hello_params); 325 hello_response = (struct ec_response_hello *)msg->data; 326 msg->insize = sizeof(*hello_response); 327 328 hello_params->in_data = 0xa0b0c0d0; 329 330 ret = send_command(ec_dev, msg); 331 332 if (ret < 0) { 333 dev_dbg(ec_dev->dev, 334 "EC failed to respond to v2 hello: %d\n", 335 ret); 336 goto exit; 337 } else if (msg->result != EC_RES_SUCCESS) { 338 dev_err(ec_dev->dev, 339 "EC responded to v2 hello with error: %d\n", 340 msg->result); 341 ret = msg->result; 342 goto exit; 343 } else if (hello_response->out_data != 0xa1b2c3d4) { 344 dev_err(ec_dev->dev, 345 "EC responded to v2 hello with bad result: %u\n", 346 hello_response->out_data); 347 ret = -EBADMSG; 348 goto exit; 349 } 350 351 ret = 0; 352 353 exit: 354 kfree(msg); 355 return ret; 356} 357 358/* 359 * cros_ec_get_host_command_version_mask 360 * 361 * Get the version mask of a given command. 362 * 363 * @ec_dev: EC device to call 364 * @msg: message structure to use 365 * @cmd: command to get the version of. 366 * @mask: result when function returns 0. 367 * 368 * @return 0 on success, error code otherwise 369 * 370 * LOCKING: 371 * the caller has ec_dev->lock mutex or the caller knows there is 372 * no other command in progress. 373 */ 374static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev, 375 u16 cmd, u32 *mask) 376{ 377 struct ec_params_get_cmd_versions *pver; 378 struct ec_response_get_cmd_versions *rver; 379 struct cros_ec_command *msg; 380 int ret; 381 382 msg = kmalloc(sizeof(*msg) + max(sizeof(*rver), sizeof(*pver)), 383 GFP_KERNEL); 384 if (!msg) 385 return -ENOMEM; 386 387 msg->version = 0; 388 msg->command = EC_CMD_GET_CMD_VERSIONS; 389 msg->insize = sizeof(*rver); 390 msg->outsize = sizeof(*pver); 391 392 pver = (struct ec_params_get_cmd_versions *)msg->data; 393 pver->cmd = cmd; 394 395 ret = send_command(ec_dev, msg); 396 if (ret > 0) { 397 rver = (struct ec_response_get_cmd_versions *)msg->data; 398 *mask = rver->version_mask; 399 } 400 401 kfree(msg); 402 403 return ret; 404} 405 406/** 407 * cros_ec_query_all() - Query the protocol version supported by the 408 * ChromeOS EC. 409 * @ec_dev: Device to register. 410 * 411 * Return: 0 on success or negative error code. 412 */ 413int cros_ec_query_all(struct cros_ec_device *ec_dev) 414{ 415 struct device *dev = ec_dev->dev; 416 struct cros_ec_command *proto_msg; 417 struct ec_response_get_protocol_info *proto_info; 418 u32 ver_mask = 0; 419 int ret; 420 421 proto_msg = kzalloc(sizeof(*proto_msg) + sizeof(*proto_info), 422 GFP_KERNEL); 423 if (!proto_msg) 424 return -ENOMEM; 425 426 /* First try sending with proto v3. */ 427 ec_dev->proto_version = 3; 428 ret = cros_ec_host_command_proto_query(ec_dev, 0, proto_msg); 429 430 if (ret == 0) { 431 proto_info = (struct ec_response_get_protocol_info *) 432 proto_msg->data; 433 ec_dev->max_request = proto_info->max_request_packet_size - 434 sizeof(struct ec_host_request); 435 ec_dev->max_response = proto_info->max_response_packet_size - 436 sizeof(struct ec_host_response); 437 ec_dev->proto_version = 438 min(EC_HOST_REQUEST_VERSION, 439 fls(proto_info->protocol_versions) - 1); 440 dev_dbg(ec_dev->dev, 441 "using proto v%u\n", 442 ec_dev->proto_version); 443 444 ec_dev->din_size = ec_dev->max_response + 445 sizeof(struct ec_host_response) + 446 EC_MAX_RESPONSE_OVERHEAD; 447 ec_dev->dout_size = ec_dev->max_request + 448 sizeof(struct ec_host_request) + 449 EC_MAX_REQUEST_OVERHEAD; 450 451 /* 452 * Check for PD 453 */ 454 ret = cros_ec_host_command_proto_query(ec_dev, 1, proto_msg); 455 456 if (ret) { 457 dev_dbg(ec_dev->dev, "no PD chip found: %d\n", ret); 458 ec_dev->max_passthru = 0; 459 } else { 460 dev_dbg(ec_dev->dev, "found PD chip\n"); 461 ec_dev->max_passthru = 462 proto_info->max_request_packet_size - 463 sizeof(struct ec_host_request); 464 } 465 } else { 466 /* Try querying with a v2 hello message. */ 467 ec_dev->proto_version = 2; 468 ret = cros_ec_host_command_proto_query_v2(ec_dev); 469 470 if (ret == 0) { 471 /* V2 hello succeeded. */ 472 dev_dbg(ec_dev->dev, "falling back to proto v2\n"); 473 474 ec_dev->max_request = EC_PROTO2_MAX_PARAM_SIZE; 475 ec_dev->max_response = EC_PROTO2_MAX_PARAM_SIZE; 476 ec_dev->max_passthru = 0; 477 ec_dev->pkt_xfer = NULL; 478 ec_dev->din_size = EC_PROTO2_MSG_BYTES; 479 ec_dev->dout_size = EC_PROTO2_MSG_BYTES; 480 } else { 481 /* 482 * It's possible for a test to occur too early when 483 * the EC isn't listening. If this happens, we'll 484 * test later when the first command is run. 485 */ 486 ec_dev->proto_version = EC_PROTO_VERSION_UNKNOWN; 487 dev_dbg(ec_dev->dev, "EC query failed: %d\n", ret); 488 goto exit; 489 } 490 } 491 492 devm_kfree(dev, ec_dev->din); 493 devm_kfree(dev, ec_dev->dout); 494 495 ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); 496 if (!ec_dev->din) { 497 ret = -ENOMEM; 498 goto exit; 499 } 500 501 ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL); 502 if (!ec_dev->dout) { 503 devm_kfree(dev, ec_dev->din); 504 ret = -ENOMEM; 505 goto exit; 506 } 507 508 /* Probe if MKBP event is supported */ 509 ret = cros_ec_get_host_command_version_mask(ec_dev, 510 EC_CMD_GET_NEXT_EVENT, 511 &ver_mask); 512 if (ret < 0 || ver_mask == 0) 513 ec_dev->mkbp_event_supported = 0; 514 else 515 ec_dev->mkbp_event_supported = fls(ver_mask); 516 517 dev_dbg(ec_dev->dev, "MKBP support version %u\n", 518 ec_dev->mkbp_event_supported - 1); 519 520 /* Probe if host sleep v1 is supported for S0ix failure detection. */ 521 ret = cros_ec_get_host_command_version_mask(ec_dev, 522 EC_CMD_HOST_SLEEP_EVENT, 523 &ver_mask); 524 ec_dev->host_sleep_v1 = (ret >= 0 && (ver_mask & EC_VER_MASK(1))); 525 526 /* Get host event wake mask. */ 527 ret = cros_ec_get_host_event_wake_mask(ec_dev, proto_msg, 528 &ec_dev->host_event_wake_mask); 529 if (ret < 0) { 530 /* 531 * If the EC doesn't support EC_CMD_HOST_EVENT_GET_WAKE_MASK, 532 * use a reasonable default. Note that we ignore various 533 * battery, AC status, and power-state events, because (a) 534 * those can be quite common (e.g., when sitting at full 535 * charge, on AC) and (b) these are not actionable wake events; 536 * if anything, we'd like to continue suspending (to save 537 * power), not wake up. 538 */ 539 ec_dev->host_event_wake_mask = U32_MAX & 540 ~(EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) | 541 EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) | 542 EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) | 543 EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) | 544 EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) | 545 EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU) | 546 EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS)); 547 /* 548 * Old ECs may not support this command. Complain about all 549 * other errors. 550 */ 551 if (ret != -EOPNOTSUPP) 552 dev_err(ec_dev->dev, 553 "failed to retrieve wake mask: %d\n", ret); 554 } 555 556 ret = 0; 557 558exit: 559 kfree(proto_msg); 560 return ret; 561} 562EXPORT_SYMBOL(cros_ec_query_all); 563 564/** 565 * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC. 566 * @ec_dev: EC device. 567 * @msg: Message to write. 568 * 569 * Call this to send a command to the ChromeOS EC. This should be used instead 570 * of calling the EC's cmd_xfer() callback directly. This function does not 571 * convert EC command execution error codes to Linux error codes. Most 572 * in-kernel users will want to use cros_ec_cmd_xfer_status() instead since 573 * that function implements the conversion. 574 * 575 * Return: 576 * >0 - EC command was executed successfully. The return value is the number 577 * of bytes returned by the EC (excluding the header). 578 * =0 - EC communication was successful. EC command execution results are 579 * reported in msg->result. The result will be EC_RES_SUCCESS if the 580 * command was executed successfully or report an EC command execution 581 * error. 582 * <0 - EC communication error. Return value is the Linux error code. 583 */ 584int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, struct cros_ec_command *msg) 585{ 586 int ret; 587 588 mutex_lock(&ec_dev->lock); 589 if (ec_dev->proto_version == EC_PROTO_VERSION_UNKNOWN) { 590 ret = cros_ec_query_all(ec_dev); 591 if (ret) { 592 dev_err(ec_dev->dev, 593 "EC version unknown and query failed; aborting command\n"); 594 mutex_unlock(&ec_dev->lock); 595 return ret; 596 } 597 } 598 599 if (msg->insize > ec_dev->max_response) { 600 dev_dbg(ec_dev->dev, "clamping message receive buffer\n"); 601 msg->insize = ec_dev->max_response; 602 } 603 604 if (msg->command < EC_CMD_PASSTHRU_OFFSET(1)) { 605 if (msg->outsize > ec_dev->max_request) { 606 dev_err(ec_dev->dev, 607 "request of size %u is too big (max: %u)\n", 608 msg->outsize, 609 ec_dev->max_request); 610 mutex_unlock(&ec_dev->lock); 611 return -EMSGSIZE; 612 } 613 } else { 614 if (msg->outsize > ec_dev->max_passthru) { 615 dev_err(ec_dev->dev, 616 "passthru rq of size %u is too big (max: %u)\n", 617 msg->outsize, 618 ec_dev->max_passthru); 619 mutex_unlock(&ec_dev->lock); 620 return -EMSGSIZE; 621 } 622 } 623 624 ret = send_command(ec_dev, msg); 625 mutex_unlock(&ec_dev->lock); 626 627 return ret; 628} 629EXPORT_SYMBOL(cros_ec_cmd_xfer); 630 631/** 632 * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC. 633 * @ec_dev: EC device. 634 * @msg: Message to write. 635 * 636 * Call this to send a command to the ChromeOS EC. This should be used instead of calling the EC's 637 * cmd_xfer() callback directly. It returns success status only if both the command was transmitted 638 * successfully and the EC replied with success status. 639 * 640 * Return: 641 * >=0 - The number of bytes transferred. 642 * <0 - Linux error code 643 */ 644int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, 645 struct cros_ec_command *msg) 646{ 647 int ret, mapped; 648 649 ret = cros_ec_cmd_xfer(ec_dev, msg); 650 if (ret < 0) 651 return ret; 652 653 mapped = cros_ec_map_error(msg->result); 654 if (mapped) { 655 dev_dbg(ec_dev->dev, "Command result (err: %d [%d])\n", 656 msg->result, mapped); 657 ret = mapped; 658 } 659 660 return ret; 661} 662EXPORT_SYMBOL(cros_ec_cmd_xfer_status); 663 664static int get_next_event_xfer(struct cros_ec_device *ec_dev, 665 struct cros_ec_command *msg, 666 struct ec_response_get_next_event_v1 *event, 667 int version, uint32_t size) 668{ 669 int ret; 670 671 msg->version = version; 672 msg->command = EC_CMD_GET_NEXT_EVENT; 673 msg->insize = size; 674 msg->outsize = 0; 675 676 ret = cros_ec_cmd_xfer_status(ec_dev, msg); 677 if (ret > 0) { 678 ec_dev->event_size = ret - 1; 679 ec_dev->event_data = *event; 680 } 681 682 return ret; 683} 684 685static int get_next_event(struct cros_ec_device *ec_dev) 686{ 687 struct { 688 struct cros_ec_command msg; 689 struct ec_response_get_next_event_v1 event; 690 } __packed buf; 691 struct cros_ec_command *msg = &buf.msg; 692 struct ec_response_get_next_event_v1 *event = &buf.event; 693 const int cmd_version = ec_dev->mkbp_event_supported - 1; 694 695 memset(msg, 0, sizeof(*msg)); 696 if (ec_dev->suspended) { 697 dev_dbg(ec_dev->dev, "Device suspended.\n"); 698 return -EHOSTDOWN; 699 } 700 701 if (cmd_version == 0) 702 return get_next_event_xfer(ec_dev, msg, event, 0, 703 sizeof(struct ec_response_get_next_event)); 704 705 return get_next_event_xfer(ec_dev, msg, event, cmd_version, 706 sizeof(struct ec_response_get_next_event_v1)); 707} 708 709static int get_keyboard_state_event(struct cros_ec_device *ec_dev) 710{ 711 u8 buffer[sizeof(struct cros_ec_command) + 712 sizeof(ec_dev->event_data.data)]; 713 struct cros_ec_command *msg = (struct cros_ec_command *)&buffer; 714 715 msg->version = 0; 716 msg->command = EC_CMD_MKBP_STATE; 717 msg->insize = sizeof(ec_dev->event_data.data); 718 msg->outsize = 0; 719 720 ec_dev->event_size = cros_ec_cmd_xfer_status(ec_dev, msg); 721 ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX; 722 memcpy(&ec_dev->event_data.data, msg->data, 723 sizeof(ec_dev->event_data.data)); 724 725 return ec_dev->event_size; 726} 727 728/** 729 * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC. 730 * @ec_dev: Device to fetch event from. 731 * @wake_event: Pointer to a bool set to true upon return if the event might be 732 * treated as a wake event. Ignored if null. 733 * @has_more_events: Pointer to bool set to true if more than one event is 734 * pending. 735 * Some EC will set this flag to indicate cros_ec_get_next_event() 736 * can be called multiple times in a row. 737 * It is an optimization to prevent issuing a EC command for 738 * nothing or wait for another interrupt from the EC to process 739 * the next message. 740 * Ignored if null. 741 * 742 * Return: negative error code on errors; 0 for no data; or else number of 743 * bytes received (i.e., an event was retrieved successfully). Event types are 744 * written out to @ec_dev->event_data.event_type on success. 745 */ 746int cros_ec_get_next_event(struct cros_ec_device *ec_dev, 747 bool *wake_event, 748 bool *has_more_events) 749{ 750 u8 event_type; 751 u32 host_event; 752 int ret; 753 754 /* 755 * Default value for wake_event. 756 * Wake up on keyboard event, wake up for spurious interrupt or link 757 * error to the EC. 758 */ 759 if (wake_event) 760 *wake_event = true; 761 762 /* 763 * Default value for has_more_events. 764 * EC will raise another interrupt if AP does not process all events 765 * anyway. 766 */ 767 if (has_more_events) 768 *has_more_events = false; 769 770 if (!ec_dev->mkbp_event_supported) 771 return get_keyboard_state_event(ec_dev); 772 773 ret = get_next_event(ec_dev); 774 if (ret <= 0) 775 return ret; 776 777 if (has_more_events) 778 *has_more_events = ec_dev->event_data.event_type & 779 EC_MKBP_HAS_MORE_EVENTS; 780 ec_dev->event_data.event_type &= EC_MKBP_EVENT_TYPE_MASK; 781 782 if (wake_event) { 783 event_type = ec_dev->event_data.event_type; 784 host_event = cros_ec_get_host_event(ec_dev); 785 786 /* 787 * Sensor events need to be parsed by the sensor sub-device. 788 * Defer them, and don't report the wakeup here. 789 */ 790 if (event_type == EC_MKBP_EVENT_SENSOR_FIFO) { 791 *wake_event = false; 792 } else if (host_event) { 793 /* rtc_update_irq() already handles wakeup events. */ 794 if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC)) 795 *wake_event = false; 796 /* Masked host-events should not count as wake events. */ 797 if (!(host_event & ec_dev->host_event_wake_mask)) 798 *wake_event = false; 799 } 800 } 801 802 return ret; 803} 804EXPORT_SYMBOL(cros_ec_get_next_event); 805 806/** 807 * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC. 808 * @ec_dev: Device to fetch event from. 809 * 810 * When MKBP is supported, when the EC raises an interrupt, we collect the 811 * events raised and call the functions in the ec notifier. This function 812 * is a helper to know which events are raised. 813 * 814 * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*. 815 */ 816u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev) 817{ 818 u32 host_event; 819 820 if (!ec_dev->mkbp_event_supported) 821 return 0; 822 823 if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT) 824 return 0; 825 826 if (ec_dev->event_size != sizeof(host_event)) { 827 dev_warn(ec_dev->dev, "Invalid host event size\n"); 828 return 0; 829 } 830 831 host_event = get_unaligned_le32(&ec_dev->event_data.data.host_event); 832 833 return host_event; 834} 835EXPORT_SYMBOL(cros_ec_get_host_event); 836 837/** 838 * cros_ec_check_features() - Test for the presence of EC features 839 * 840 * @ec: EC device, does not have to be connected directly to the AP, 841 * can be daisy chained through another device. 842 * @feature: One of ec_feature_code bit. 843 * 844 * Call this function to test whether the ChromeOS EC supports a feature. 845 * 846 * Return: true if supported, false if not (or if an error was encountered). 847 */ 848bool cros_ec_check_features(struct cros_ec_dev *ec, int feature) 849{ 850 struct ec_response_get_features *features = &ec->features; 851 int ret; 852 853 if (features->flags[0] == -1U && features->flags[1] == -1U) { 854 /* features bitmap not read yet */ 855 ret = cros_ec_command(ec->ec_dev, 0, EC_CMD_GET_FEATURES + ec->cmd_offset, 856 NULL, 0, features, sizeof(*features)); 857 if (ret < 0) { 858 dev_warn(ec->dev, "cannot get EC features: %d\n", ret); 859 memset(features, 0, sizeof(*features)); 860 } 861 862 dev_dbg(ec->dev, "EC features %08x %08x\n", 863 features->flags[0], features->flags[1]); 864 } 865 866 return !!(features->flags[feature / 32] & EC_FEATURE_MASK_0(feature)); 867} 868EXPORT_SYMBOL_GPL(cros_ec_check_features); 869 870/** 871 * cros_ec_get_sensor_count() - Return the number of MEMS sensors supported. 872 * 873 * @ec: EC device, does not have to be connected directly to the AP, 874 * can be daisy chained through another device. 875 * Return: < 0 in case of error. 876 */ 877int cros_ec_get_sensor_count(struct cros_ec_dev *ec) 878{ 879 /* 880 * Issue a command to get the number of sensor reported. 881 * If not supported, check for legacy mode. 882 */ 883 int ret, sensor_count; 884 struct ec_params_motion_sense *params; 885 struct ec_response_motion_sense *resp; 886 struct cros_ec_command *msg; 887 struct cros_ec_device *ec_dev = ec->ec_dev; 888 u8 status; 889 890 msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*resp)), 891 GFP_KERNEL); 892 if (!msg) 893 return -ENOMEM; 894 895 msg->version = 1; 896 msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; 897 msg->outsize = sizeof(*params); 898 msg->insize = sizeof(*resp); 899 900 params = (struct ec_params_motion_sense *)msg->data; 901 params->cmd = MOTIONSENSE_CMD_DUMP; 902 903 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 904 if (ret < 0) { 905 sensor_count = ret; 906 } else { 907 resp = (struct ec_response_motion_sense *)msg->data; 908 sensor_count = resp->dump.sensor_count; 909 } 910 kfree(msg); 911 912 /* 913 * Check legacy mode: Let's find out if sensors are accessible 914 * via LPC interface. 915 */ 916 if (sensor_count < 0 && ec->cmd_offset == 0 && ec_dev->cmd_readmem) { 917 ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, 918 1, &status); 919 if (ret >= 0 && 920 (status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) { 921 /* 922 * We have 2 sensors, one in the lid, one in the base. 923 */ 924 sensor_count = 2; 925 } else { 926 /* 927 * EC uses LPC interface and no sensors are presented. 928 */ 929 sensor_count = 0; 930 } 931 } 932 return sensor_count; 933} 934EXPORT_SYMBOL_GPL(cros_ec_get_sensor_count); 935 936/** 937 * cros_ec_command - Send a command to the EC. 938 * 939 * @ec_dev: EC device 940 * @version: EC command version 941 * @command: EC command 942 * @outdata: EC command output data 943 * @outsize: Size of outdata 944 * @indata: EC command input data 945 * @insize: Size of indata 946 * 947 * Return: >= 0 on success, negative error number on failure. 948 */ 949int cros_ec_command(struct cros_ec_device *ec_dev, 950 unsigned int version, 951 int command, 952 void *outdata, 953 int outsize, 954 void *indata, 955 int insize) 956{ 957 struct cros_ec_command *msg; 958 int ret; 959 960 msg = kzalloc(sizeof(*msg) + max(insize, outsize), GFP_KERNEL); 961 if (!msg) 962 return -ENOMEM; 963 964 msg->version = version; 965 msg->command = command; 966 msg->outsize = outsize; 967 msg->insize = insize; 968 969 if (outsize) 970 memcpy(msg->data, outdata, outsize); 971 972 ret = cros_ec_cmd_xfer_status(ec_dev, msg); 973 if (ret < 0) 974 goto error; 975 976 if (insize) 977 memcpy(indata, msg->data, insize); 978error: 979 kfree(msg); 980 return ret; 981} 982EXPORT_SYMBOL_GPL(cros_ec_command);