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 r = (struct ec_response_host_event_mask *)msg->data; 213 *mask = r->mask; 214 } 215 216 return ret; 217 } 218 219 static int cros_ec_host_command_proto_query(struct cros_ec_device *ec_dev, 220 int devidx, 221 struct cros_ec_command *msg) 222 { 223 /* 224 * Try using v3+ to query for supported protocols. If this 225 * command fails, fall back to v2. Returns the highest protocol 226 * supported by the EC. 227 * Also sets the max request/response/passthru size. 228 */ 229 int ret; 230 231 if (!ec_dev->pkt_xfer) 232 return -EPROTONOSUPPORT; 233 234 memset(msg, 0, sizeof(*msg)); 235 msg->command = EC_CMD_PASSTHRU_OFFSET(devidx) | EC_CMD_GET_PROTOCOL_INFO; 236 msg->insize = sizeof(struct ec_response_get_protocol_info); 237 238 ret = send_command(ec_dev, msg); 239 240 if (ret < 0) { 241 dev_dbg(ec_dev->dev, 242 "failed to check for EC[%d] protocol version: %d\n", 243 devidx, ret); 244 return ret; 245 } 246 247 if (devidx > 0 && msg->result == EC_RES_INVALID_COMMAND) 248 return -ENODEV; 249 else if (msg->result != EC_RES_SUCCESS) 250 return msg->result; 251 252 return 0; 253 } 254 255 static int cros_ec_host_command_proto_query_v2(struct cros_ec_device *ec_dev) 256 { 257 struct cros_ec_command *msg; 258 struct ec_params_hello *hello_params; 259 struct ec_response_hello *hello_response; 260 int ret; 261 int len = max(sizeof(*hello_params), sizeof(*hello_response)); 262 263 msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL); 264 if (!msg) 265 return -ENOMEM; 266 267 msg->version = 0; 268 msg->command = EC_CMD_HELLO; 269 hello_params = (struct ec_params_hello *)msg->data; 270 msg->outsize = sizeof(*hello_params); 271 hello_response = (struct ec_response_hello *)msg->data; 272 msg->insize = sizeof(*hello_response); 273 274 hello_params->in_data = 0xa0b0c0d0; 275 276 ret = send_command(ec_dev, msg); 277 278 if (ret < 0) { 279 dev_dbg(ec_dev->dev, 280 "EC failed to respond to v2 hello: %d\n", 281 ret); 282 goto exit; 283 } else if (msg->result != EC_RES_SUCCESS) { 284 dev_err(ec_dev->dev, 285 "EC responded to v2 hello with error: %d\n", 286 msg->result); 287 ret = msg->result; 288 goto exit; 289 } else if (hello_response->out_data != 0xa1b2c3d4) { 290 dev_err(ec_dev->dev, 291 "EC responded to v2 hello with bad result: %u\n", 292 hello_response->out_data); 293 ret = -EBADMSG; 294 goto exit; 295 } 296 297 ret = 0; 298 299 exit: 300 kfree(msg); 301 return ret; 302 } 303 304 /* 305 * cros_ec_get_host_command_version_mask 306 * 307 * Get the version mask of a given command. 308 * 309 * @ec_dev: EC device to call 310 * @msg: message structure to use 311 * @cmd: command to get the version of. 312 * @mask: result when function returns 0. 313 * 314 * @return 0 on success, error code otherwise 315 * 316 * LOCKING: 317 * the caller has ec_dev->lock mutex or the caller knows there is 318 * no other command in progress. 319 */ 320 static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev, 321 u16 cmd, u32 *mask) 322 { 323 struct ec_params_get_cmd_versions *pver; 324 struct ec_response_get_cmd_versions *rver; 325 struct cros_ec_command *msg; 326 int ret; 327 328 msg = kmalloc(sizeof(*msg) + max(sizeof(*rver), sizeof(*pver)), 329 GFP_KERNEL); 330 if (!msg) 331 return -ENOMEM; 332 333 msg->version = 0; 334 msg->command = EC_CMD_GET_CMD_VERSIONS; 335 msg->insize = sizeof(*rver); 336 msg->outsize = sizeof(*pver); 337 338 pver = (struct ec_params_get_cmd_versions *)msg->data; 339 pver->cmd = cmd; 340 341 ret = send_command(ec_dev, msg); 342 if (ret > 0) { 343 rver = (struct ec_response_get_cmd_versions *)msg->data; 344 *mask = rver->version_mask; 345 } 346 347 kfree(msg); 348 349 return ret; 350 } 351 352 /** 353 * cros_ec_query_all() - Query the protocol version supported by the 354 * ChromeOS EC. 355 * @ec_dev: Device to register. 356 * 357 * Return: 0 on success or negative error code. 358 */ 359 int cros_ec_query_all(struct cros_ec_device *ec_dev) 360 { 361 struct device *dev = ec_dev->dev; 362 struct cros_ec_command *proto_msg; 363 struct ec_response_get_protocol_info *proto_info; 364 u32 ver_mask = 0; 365 int ret; 366 367 proto_msg = kzalloc(sizeof(*proto_msg) + sizeof(*proto_info), 368 GFP_KERNEL); 369 if (!proto_msg) 370 return -ENOMEM; 371 372 /* First try sending with proto v3. */ 373 ec_dev->proto_version = 3; 374 ret = cros_ec_host_command_proto_query(ec_dev, 0, proto_msg); 375 376 if (ret == 0) { 377 proto_info = (struct ec_response_get_protocol_info *) 378 proto_msg->data; 379 ec_dev->max_request = proto_info->max_request_packet_size - 380 sizeof(struct ec_host_request); 381 ec_dev->max_response = proto_info->max_response_packet_size - 382 sizeof(struct ec_host_response); 383 ec_dev->proto_version = 384 min(EC_HOST_REQUEST_VERSION, 385 fls(proto_info->protocol_versions) - 1); 386 dev_dbg(ec_dev->dev, 387 "using proto v%u\n", 388 ec_dev->proto_version); 389 390 ec_dev->din_size = ec_dev->max_response + 391 sizeof(struct ec_host_response) + 392 EC_MAX_RESPONSE_OVERHEAD; 393 ec_dev->dout_size = ec_dev->max_request + 394 sizeof(struct ec_host_request) + 395 EC_MAX_REQUEST_OVERHEAD; 396 397 /* 398 * Check for PD 399 */ 400 ret = cros_ec_host_command_proto_query(ec_dev, 1, proto_msg); 401 402 if (ret) { 403 dev_dbg(ec_dev->dev, "no PD chip found: %d\n", ret); 404 ec_dev->max_passthru = 0; 405 } else { 406 dev_dbg(ec_dev->dev, "found PD chip\n"); 407 ec_dev->max_passthru = 408 proto_info->max_request_packet_size - 409 sizeof(struct ec_host_request); 410 } 411 } else { 412 /* Try querying with a v2 hello message. */ 413 ec_dev->proto_version = 2; 414 ret = cros_ec_host_command_proto_query_v2(ec_dev); 415 416 if (ret == 0) { 417 /* V2 hello succeeded. */ 418 dev_dbg(ec_dev->dev, "falling back to proto v2\n"); 419 420 ec_dev->max_request = EC_PROTO2_MAX_PARAM_SIZE; 421 ec_dev->max_response = EC_PROTO2_MAX_PARAM_SIZE; 422 ec_dev->max_passthru = 0; 423 ec_dev->pkt_xfer = NULL; 424 ec_dev->din_size = EC_PROTO2_MSG_BYTES; 425 ec_dev->dout_size = EC_PROTO2_MSG_BYTES; 426 } else { 427 /* 428 * It's possible for a test to occur too early when 429 * the EC isn't listening. If this happens, we'll 430 * test later when the first command is run. 431 */ 432 ec_dev->proto_version = EC_PROTO_VERSION_UNKNOWN; 433 dev_dbg(ec_dev->dev, "EC query failed: %d\n", ret); 434 goto exit; 435 } 436 } 437 438 devm_kfree(dev, ec_dev->din); 439 devm_kfree(dev, ec_dev->dout); 440 441 ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); 442 if (!ec_dev->din) { 443 ret = -ENOMEM; 444 goto exit; 445 } 446 447 ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL); 448 if (!ec_dev->dout) { 449 devm_kfree(dev, ec_dev->din); 450 ret = -ENOMEM; 451 goto exit; 452 } 453 454 /* Probe if MKBP event is supported */ 455 ret = cros_ec_get_host_command_version_mask(ec_dev, 456 EC_CMD_GET_NEXT_EVENT, 457 &ver_mask); 458 if (ret < 0 || ver_mask == 0) 459 ec_dev->mkbp_event_supported = 0; 460 else 461 ec_dev->mkbp_event_supported = fls(ver_mask); 462 463 dev_dbg(ec_dev->dev, "MKBP support version %u\n", 464 ec_dev->mkbp_event_supported - 1); 465 466 /* Probe if host sleep v1 is supported for S0ix failure detection. */ 467 ret = cros_ec_get_host_command_version_mask(ec_dev, 468 EC_CMD_HOST_SLEEP_EVENT, 469 &ver_mask); 470 ec_dev->host_sleep_v1 = (ret >= 0 && (ver_mask & EC_VER_MASK(1))); 471 472 /* 473 * Get host event wake mask, assume all events are wake events 474 * if unavailable. 475 */ 476 ret = cros_ec_get_host_event_wake_mask(ec_dev, proto_msg, 477 &ec_dev->host_event_wake_mask); 478 if (ret < 0) 479 ec_dev->host_event_wake_mask = U32_MAX; 480 481 ret = 0; 482 483 exit: 484 kfree(proto_msg); 485 return ret; 486 } 487 EXPORT_SYMBOL(cros_ec_query_all); 488 489 /** 490 * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC. 491 * @ec_dev: EC device. 492 * @msg: Message to write. 493 * 494 * Call this to send a command to the ChromeOS EC. This should be used 495 * instead of calling the EC's cmd_xfer() callback directly. 496 * 497 * Return: 0 on success or negative error code. 498 */ 499 int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, 500 struct cros_ec_command *msg) 501 { 502 int ret; 503 504 mutex_lock(&ec_dev->lock); 505 if (ec_dev->proto_version == EC_PROTO_VERSION_UNKNOWN) { 506 ret = cros_ec_query_all(ec_dev); 507 if (ret) { 508 dev_err(ec_dev->dev, 509 "EC version unknown and query failed; aborting command\n"); 510 mutex_unlock(&ec_dev->lock); 511 return ret; 512 } 513 } 514 515 if (msg->insize > ec_dev->max_response) { 516 dev_dbg(ec_dev->dev, "clamping message receive buffer\n"); 517 msg->insize = ec_dev->max_response; 518 } 519 520 if (msg->command < EC_CMD_PASSTHRU_OFFSET(1)) { 521 if (msg->outsize > ec_dev->max_request) { 522 dev_err(ec_dev->dev, 523 "request of size %u is too big (max: %u)\n", 524 msg->outsize, 525 ec_dev->max_request); 526 mutex_unlock(&ec_dev->lock); 527 return -EMSGSIZE; 528 } 529 } else { 530 if (msg->outsize > ec_dev->max_passthru) { 531 dev_err(ec_dev->dev, 532 "passthru rq of size %u is too big (max: %u)\n", 533 msg->outsize, 534 ec_dev->max_passthru); 535 mutex_unlock(&ec_dev->lock); 536 return -EMSGSIZE; 537 } 538 } 539 ret = send_command(ec_dev, msg); 540 mutex_unlock(&ec_dev->lock); 541 542 return ret; 543 } 544 EXPORT_SYMBOL(cros_ec_cmd_xfer); 545 546 /** 547 * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC. 548 * @ec_dev: EC device. 549 * @msg: Message to write. 550 * 551 * This function is identical to cros_ec_cmd_xfer, except it returns success 552 * status only if both the command was transmitted successfully and the EC 553 * replied with success status. It's not necessary to check msg->result when 554 * using this function. 555 * 556 * Return: 557 * >=0 - The number of bytes transferred 558 * -ENOTSUPP - Operation not supported 559 * -EPROTO - Protocol error 560 */ 561 int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev, 562 struct cros_ec_command *msg) 563 { 564 int ret; 565 566 ret = cros_ec_cmd_xfer(ec_dev, msg); 567 if (ret < 0) { 568 dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret); 569 } else if (msg->result == EC_RES_INVALID_VERSION) { 570 dev_dbg(ec_dev->dev, "Command invalid version (err:%d)\n", 571 msg->result); 572 return -ENOTSUPP; 573 } else if (msg->result != EC_RES_SUCCESS) { 574 dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result); 575 return -EPROTO; 576 } 577 578 return ret; 579 } 580 EXPORT_SYMBOL(cros_ec_cmd_xfer_status); 581 582 static int get_next_event_xfer(struct cros_ec_device *ec_dev, 583 struct cros_ec_command *msg, 584 struct ec_response_get_next_event_v1 *event, 585 int version, uint32_t size) 586 { 587 int ret; 588 589 msg->version = version; 590 msg->command = EC_CMD_GET_NEXT_EVENT; 591 msg->insize = size; 592 msg->outsize = 0; 593 594 ret = cros_ec_cmd_xfer(ec_dev, msg); 595 if (ret > 0) { 596 ec_dev->event_size = ret - 1; 597 ec_dev->event_data = *event; 598 } 599 600 return ret; 601 } 602 603 static int get_next_event(struct cros_ec_device *ec_dev) 604 { 605 struct { 606 struct cros_ec_command msg; 607 struct ec_response_get_next_event_v1 event; 608 } __packed buf; 609 struct cros_ec_command *msg = &buf.msg; 610 struct ec_response_get_next_event_v1 *event = &buf.event; 611 const int cmd_version = ec_dev->mkbp_event_supported - 1; 612 613 memset(msg, 0, sizeof(*msg)); 614 if (ec_dev->suspended) { 615 dev_dbg(ec_dev->dev, "Device suspended.\n"); 616 return -EHOSTDOWN; 617 } 618 619 if (cmd_version == 0) 620 return get_next_event_xfer(ec_dev, msg, event, 0, 621 sizeof(struct ec_response_get_next_event)); 622 623 return get_next_event_xfer(ec_dev, msg, event, cmd_version, 624 sizeof(struct ec_response_get_next_event_v1)); 625 } 626 627 static int get_keyboard_state_event(struct cros_ec_device *ec_dev) 628 { 629 u8 buffer[sizeof(struct cros_ec_command) + 630 sizeof(ec_dev->event_data.data)]; 631 struct cros_ec_command *msg = (struct cros_ec_command *)&buffer; 632 633 msg->version = 0; 634 msg->command = EC_CMD_MKBP_STATE; 635 msg->insize = sizeof(ec_dev->event_data.data); 636 msg->outsize = 0; 637 638 ec_dev->event_size = cros_ec_cmd_xfer(ec_dev, msg); 639 ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX; 640 memcpy(&ec_dev->event_data.data, msg->data, 641 sizeof(ec_dev->event_data.data)); 642 643 return ec_dev->event_size; 644 } 645 646 /** 647 * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC. 648 * @ec_dev: Device to fetch event from. 649 * @wake_event: Pointer to a bool set to true upon return if the event might be 650 * treated as a wake event. Ignored if null. 651 * @has_more_events: Pointer to bool set to true if more than one event is 652 * pending. 653 * Some EC will set this flag to indicate cros_ec_get_next_event() 654 * can be called multiple times in a row. 655 * It is an optimization to prevent issuing a EC command for 656 * nothing or wait for another interrupt from the EC to process 657 * the next message. 658 * Ignored if null. 659 * 660 * Return: negative error code on errors; 0 for no data; or else number of 661 * bytes received (i.e., an event was retrieved successfully). Event types are 662 * written out to @ec_dev->event_data.event_type on success. 663 */ 664 int cros_ec_get_next_event(struct cros_ec_device *ec_dev, 665 bool *wake_event, 666 bool *has_more_events) 667 { 668 u8 event_type; 669 u32 host_event; 670 int ret; 671 672 /* 673 * Default value for wake_event. 674 * Wake up on keyboard event, wake up for spurious interrupt or link 675 * error to the EC. 676 */ 677 if (wake_event) 678 *wake_event = true; 679 680 /* 681 * Default value for has_more_events. 682 * EC will raise another interrupt if AP does not process all events 683 * anyway. 684 */ 685 if (has_more_events) 686 *has_more_events = false; 687 688 if (!ec_dev->mkbp_event_supported) 689 return get_keyboard_state_event(ec_dev); 690 691 ret = get_next_event(ec_dev); 692 if (ret <= 0) 693 return ret; 694 695 if (has_more_events) 696 *has_more_events = ec_dev->event_data.event_type & 697 EC_MKBP_HAS_MORE_EVENTS; 698 ec_dev->event_data.event_type &= EC_MKBP_EVENT_TYPE_MASK; 699 700 if (wake_event) { 701 event_type = ec_dev->event_data.event_type; 702 host_event = cros_ec_get_host_event(ec_dev); 703 704 /* 705 * Sensor events need to be parsed by the sensor sub-device. 706 * Defer them, and don't report the wakeup here. 707 */ 708 if (event_type == EC_MKBP_EVENT_SENSOR_FIFO) 709 *wake_event = false; 710 /* Masked host-events should not count as wake events. */ 711 else if (host_event && 712 !(host_event & ec_dev->host_event_wake_mask)) 713 *wake_event = false; 714 } 715 716 return ret; 717 } 718 EXPORT_SYMBOL(cros_ec_get_next_event); 719 720 /** 721 * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC. 722 * @ec_dev: Device to fetch event from. 723 * 724 * When MKBP is supported, when the EC raises an interrupt, we collect the 725 * events raised and call the functions in the ec notifier. This function 726 * is a helper to know which events are raised. 727 * 728 * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*. 729 */ 730 u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev) 731 { 732 u32 host_event; 733 734 BUG_ON(!ec_dev->mkbp_event_supported); 735 736 if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT) 737 return 0; 738 739 if (ec_dev->event_size != sizeof(host_event)) { 740 dev_warn(ec_dev->dev, "Invalid host event size\n"); 741 return 0; 742 } 743 744 host_event = get_unaligned_le32(&ec_dev->event_data.data.host_event); 745 746 return host_event; 747 } 748 EXPORT_SYMBOL(cros_ec_get_host_event); 749 750 /** 751 * cros_ec_check_features() - Test for the presence of EC features 752 * 753 * @ec: EC device, does not have to be connected directly to the AP, 754 * can be daisy chained through another device. 755 * @feature: One of ec_feature_code bit. 756 * 757 * Call this function to test whether the ChromeOS EC supports a feature. 758 * 759 * Return: 1 if supported, 0 if not 760 */ 761 int cros_ec_check_features(struct cros_ec_dev *ec, int feature) 762 { 763 struct cros_ec_command *msg; 764 int ret; 765 766 if (ec->features[0] == -1U && ec->features[1] == -1U) { 767 /* features bitmap not read yet */ 768 msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL); 769 if (!msg) 770 return -ENOMEM; 771 772 msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset; 773 msg->insize = sizeof(ec->features); 774 775 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); 776 if (ret < 0) { 777 dev_warn(ec->dev, "cannot get EC features: %d/%d\n", 778 ret, msg->result); 779 memset(ec->features, 0, sizeof(ec->features)); 780 } else { 781 memcpy(ec->features, msg->data, sizeof(ec->features)); 782 } 783 784 dev_dbg(ec->dev, "EC features %08x %08x\n", 785 ec->features[0], ec->features[1]); 786 787 kfree(msg); 788 } 789 790 return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature); 791 } 792 EXPORT_SYMBOL_GPL(cros_ec_check_features); 793 794 /** 795 * cros_ec_get_sensor_count() - Return the number of MEMS sensors supported. 796 * 797 * @ec: EC device, does not have to be connected directly to the AP, 798 * can be daisy chained through another device. 799 * Return: < 0 in case of error. 800 */ 801 int cros_ec_get_sensor_count(struct cros_ec_dev *ec) 802 { 803 /* 804 * Issue a command to get the number of sensor reported. 805 * If not supported, check for legacy mode. 806 */ 807 int ret, sensor_count; 808 struct ec_params_motion_sense *params; 809 struct ec_response_motion_sense *resp; 810 struct cros_ec_command *msg; 811 struct cros_ec_device *ec_dev = ec->ec_dev; 812 u8 status; 813 814 msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*resp)), 815 GFP_KERNEL); 816 if (!msg) 817 return -ENOMEM; 818 819 msg->version = 1; 820 msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; 821 msg->outsize = sizeof(*params); 822 msg->insize = sizeof(*resp); 823 824 params = (struct ec_params_motion_sense *)msg->data; 825 params->cmd = MOTIONSENSE_CMD_DUMP; 826 827 ret = cros_ec_cmd_xfer(ec->ec_dev, msg); 828 if (ret < 0) { 829 sensor_count = ret; 830 } else if (msg->result != EC_RES_SUCCESS) { 831 sensor_count = -EPROTO; 832 } else { 833 resp = (struct ec_response_motion_sense *)msg->data; 834 sensor_count = resp->dump.sensor_count; 835 } 836 kfree(msg); 837 838 /* 839 * Check legacy mode: Let's find out if sensors are accessible 840 * via LPC interface. 841 */ 842 if (sensor_count == -EPROTO && 843 ec->cmd_offset == 0 && 844 ec_dev->cmd_readmem) { 845 ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, 846 1, &status); 847 if (ret >= 0 && 848 (status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) { 849 /* 850 * We have 2 sensors, one in the lid, one in the base. 851 */ 852 sensor_count = 2; 853 } else { 854 /* 855 * EC uses LPC interface and no sensors are presented. 856 */ 857 sensor_count = 0; 858 } 859 } else if (sensor_count == -EPROTO) { 860 /* EC responded, but does not understand DUMP command. */ 861 sensor_count = 0; 862 } 863 return sensor_count; 864 } 865 EXPORT_SYMBOL_GPL(cros_ec_get_sensor_count); 866