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