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