Lines Matching +full:host +full:- +full:wake
1 // SPDX-License-Identifier: GPL-2.0
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,
49 ret = -EPROTO; in cros_ec_map_error()
63 BUG_ON(ec_dev->proto_version != EC_HOST_REQUEST_VERSION); in prepare_packet()
64 BUG_ON(msg->outsize + sizeof(*request) > ec_dev->dout_size); in prepare_packet()
66 out = ec_dev->dout; in prepare_packet()
68 request->struct_version = EC_HOST_REQUEST_VERSION; in prepare_packet()
69 request->checksum = 0; in prepare_packet()
70 request->command = msg->command; in prepare_packet()
71 request->command_version = msg->version; in prepare_packet()
72 request->reserved = 0; in prepare_packet()
73 request->data_len = msg->outsize; in prepare_packet()
79 memcpy(out + sizeof(*request), msg->data, msg->outsize); in prepare_packet()
80 for (i = 0; i < msg->outsize; i++) in prepare_packet()
81 csum += msg->data[i]; in prepare_packet()
83 request->checksum = -csum; in prepare_packet()
85 return sizeof(*request) + msg->outsize; in prepare_packet()
94 if (ec_dev->proto_version > 2) in send_command()
95 xfer_fxn = ec_dev->pkt_xfer; in send_command()
97 xfer_fxn = ec_dev->cmd_xfer; in send_command()
105 dev_err_once(ec_dev->dev, in send_command()
107 return -EIO; in send_command()
113 if (msg->result == EC_RES_IN_PROGRESS) { in send_command()
121 return -ENOMEM; in send_command()
123 status_msg->version = 0; in send_command()
124 status_msg->command = EC_CMD_GET_COMMS_STATUS; in send_command()
125 status_msg->insize = sizeof(*status); in send_command()
126 status_msg->outsize = 0; in send_command()
138 if (ret == -EAGAIN) in send_command()
143 msg->result = status_msg->result; in send_command()
144 if (status_msg->result != EC_RES_SUCCESS) in send_command()
148 status_msg->data; in send_command()
149 if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) in send_command()
160 * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
177 if (ec_dev->proto_version > 2) in cros_ec_prepare_tx()
180 BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE); in cros_ec_prepare_tx()
181 out = ec_dev->dout; in cros_ec_prepare_tx()
182 out[0] = EC_CMD_VERSION0 + msg->version; in cros_ec_prepare_tx()
183 out[1] = msg->command; in cros_ec_prepare_tx()
184 out[2] = msg->outsize; in cros_ec_prepare_tx()
186 for (i = 0; i < msg->outsize; i++) in cros_ec_prepare_tx()
187 csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->data[i]; in cros_ec_prepare_tx()
188 out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = csum; in cros_ec_prepare_tx()
190 return EC_MSG_TX_PROTO_BYTES + msg->outsize; in cros_ec_prepare_tx()
195 * cros_ec_check_result() - Check ec_msg->result.
199 * This is used by ChromeOS EC drivers to check the ec_msg->result for
207 switch (msg->result) { in cros_ec_check_result()
211 dev_dbg(ec_dev->dev, "command 0x%02x in progress\n", in cros_ec_check_result()
212 msg->command); in cros_ec_check_result()
213 return -EAGAIN; in cros_ec_check_result()
215 dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n", in cros_ec_check_result()
216 msg->command, msg->result); in cros_ec_check_result()
225 * Get the mask of host events that cause wake from suspend.
232 * the caller has ec_dev->lock mutex, or the caller knows there is
242 msg->command = EC_CMD_HOST_EVENT_GET_WAKE_MASK; in cros_ec_get_host_event_wake_mask()
243 msg->version = 0; in cros_ec_get_host_event_wake_mask()
244 msg->outsize = 0; in cros_ec_get_host_event_wake_mask()
245 msg->insize = sizeof(*r); in cros_ec_get_host_event_wake_mask()
249 if (msg->result == EC_RES_INVALID_COMMAND) in cros_ec_get_host_event_wake_mask()
250 return -EOPNOTSUPP; in cros_ec_get_host_event_wake_mask()
251 if (msg->result != EC_RES_SUCCESS) in cros_ec_get_host_event_wake_mask()
252 return -EPROTO; in cros_ec_get_host_event_wake_mask()
255 r = (struct ec_response_host_event_mask *)msg->data; in cros_ec_get_host_event_wake_mask()
256 *mask = r->mask; in cros_ec_get_host_event_wake_mask()
274 if (!ec_dev->pkt_xfer) in cros_ec_host_command_proto_query()
275 return -EPROTONOSUPPORT; in cros_ec_host_command_proto_query()
278 msg->command = EC_CMD_PASSTHRU_OFFSET(devidx) | EC_CMD_GET_PROTOCOL_INFO; in cros_ec_host_command_proto_query()
279 msg->insize = sizeof(struct ec_response_get_protocol_info); in cros_ec_host_command_proto_query()
284 dev_dbg(ec_dev->dev, in cros_ec_host_command_proto_query()
290 if (devidx > 0 && msg->result == EC_RES_INVALID_COMMAND) in cros_ec_host_command_proto_query()
291 return -ENODEV; in cros_ec_host_command_proto_query()
292 else if (msg->result != EC_RES_SUCCESS) in cros_ec_host_command_proto_query()
293 return msg->result; in cros_ec_host_command_proto_query()
308 return -ENOMEM; in cros_ec_host_command_proto_query_v2()
310 msg->version = 0; in cros_ec_host_command_proto_query_v2()
311 msg->command = EC_CMD_HELLO; in cros_ec_host_command_proto_query_v2()
312 hello_params = (struct ec_params_hello *)msg->data; in cros_ec_host_command_proto_query_v2()
313 msg->outsize = sizeof(*hello_params); in cros_ec_host_command_proto_query_v2()
314 hello_response = (struct ec_response_hello *)msg->data; in cros_ec_host_command_proto_query_v2()
315 msg->insize = sizeof(*hello_response); in cros_ec_host_command_proto_query_v2()
317 hello_params->in_data = 0xa0b0c0d0; in cros_ec_host_command_proto_query_v2()
322 dev_dbg(ec_dev->dev, in cros_ec_host_command_proto_query_v2()
326 } else if (msg->result != EC_RES_SUCCESS) { in cros_ec_host_command_proto_query_v2()
327 dev_err(ec_dev->dev, in cros_ec_host_command_proto_query_v2()
329 msg->result); in cros_ec_host_command_proto_query_v2()
330 ret = msg->result; in cros_ec_host_command_proto_query_v2()
332 } else if (hello_response->out_data != 0xa1b2c3d4) { in cros_ec_host_command_proto_query_v2()
333 dev_err(ec_dev->dev, in cros_ec_host_command_proto_query_v2()
335 hello_response->out_data); in cros_ec_host_command_proto_query_v2()
336 ret = -EBADMSG; in cros_ec_host_command_proto_query_v2()
360 * the caller has ec_dev->lock mutex or the caller knows there is
374 return -ENOMEM; in cros_ec_get_host_command_version_mask()
376 msg->version = 0; in cros_ec_get_host_command_version_mask()
377 msg->command = EC_CMD_GET_CMD_VERSIONS; in cros_ec_get_host_command_version_mask()
378 msg->insize = sizeof(*rver); in cros_ec_get_host_command_version_mask()
379 msg->outsize = sizeof(*pver); in cros_ec_get_host_command_version_mask()
381 pver = (struct ec_params_get_cmd_versions *)msg->data; in cros_ec_get_host_command_version_mask()
382 pver->cmd = cmd; in cros_ec_get_host_command_version_mask()
386 rver = (struct ec_response_get_cmd_versions *)msg->data; in cros_ec_get_host_command_version_mask()
387 *mask = rver->version_mask; in cros_ec_get_host_command_version_mask()
396 * cros_ec_query_all() - Query the protocol version supported by the
404 struct device *dev = ec_dev->dev; in cros_ec_query_all()
413 return -ENOMEM; in cros_ec_query_all()
416 ec_dev->proto_version = 3; in cros_ec_query_all()
421 proto_msg->data; in cros_ec_query_all()
422 ec_dev->max_request = proto_info->max_request_packet_size - in cros_ec_query_all()
424 ec_dev->max_response = proto_info->max_response_packet_size - in cros_ec_query_all()
426 ec_dev->proto_version = in cros_ec_query_all()
428 fls(proto_info->protocol_versions) - 1); in cros_ec_query_all()
429 dev_dbg(ec_dev->dev, in cros_ec_query_all()
431 ec_dev->proto_version); in cros_ec_query_all()
433 ec_dev->din_size = ec_dev->max_response + in cros_ec_query_all()
436 ec_dev->dout_size = ec_dev->max_request + in cros_ec_query_all()
446 dev_dbg(ec_dev->dev, "no PD chip found: %d\n", ret); in cros_ec_query_all()
447 ec_dev->max_passthru = 0; in cros_ec_query_all()
449 dev_dbg(ec_dev->dev, "found PD chip\n"); in cros_ec_query_all()
450 ec_dev->max_passthru = in cros_ec_query_all()
451 proto_info->max_request_packet_size - in cros_ec_query_all()
456 ec_dev->proto_version = 2; in cros_ec_query_all()
461 dev_dbg(ec_dev->dev, "falling back to proto v2\n"); in cros_ec_query_all()
463 ec_dev->max_request = EC_PROTO2_MAX_PARAM_SIZE; in cros_ec_query_all()
464 ec_dev->max_response = EC_PROTO2_MAX_PARAM_SIZE; in cros_ec_query_all()
465 ec_dev->max_passthru = 0; in cros_ec_query_all()
466 ec_dev->pkt_xfer = NULL; in cros_ec_query_all()
467 ec_dev->din_size = EC_PROTO2_MSG_BYTES; in cros_ec_query_all()
468 ec_dev->dout_size = EC_PROTO2_MSG_BYTES; in cros_ec_query_all()
475 ec_dev->proto_version = EC_PROTO_VERSION_UNKNOWN; in cros_ec_query_all()
476 dev_dbg(ec_dev->dev, "EC query failed: %d\n", ret); in cros_ec_query_all()
481 devm_kfree(dev, ec_dev->din); in cros_ec_query_all()
482 devm_kfree(dev, ec_dev->dout); in cros_ec_query_all()
484 ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); in cros_ec_query_all()
485 if (!ec_dev->din) { in cros_ec_query_all()
486 ret = -ENOMEM; in cros_ec_query_all()
490 ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL); in cros_ec_query_all()
491 if (!ec_dev->dout) { in cros_ec_query_all()
492 devm_kfree(dev, ec_dev->din); in cros_ec_query_all()
493 ret = -ENOMEM; in cros_ec_query_all()
502 ec_dev->mkbp_event_supported = 0; in cros_ec_query_all()
504 ec_dev->mkbp_event_supported = fls(ver_mask); in cros_ec_query_all()
506 dev_dbg(ec_dev->dev, "MKBP support version %u\n", in cros_ec_query_all()
507 ec_dev->mkbp_event_supported - 1); in cros_ec_query_all()
509 /* Probe if host sleep v1 is supported for S0ix failure detection. */ in cros_ec_query_all()
513 ec_dev->host_sleep_v1 = (ret >= 0 && (ver_mask & EC_VER_MASK(1))); in cros_ec_query_all()
515 /* Get host event wake mask. */ in cros_ec_query_all()
517 &ec_dev->host_event_wake_mask); in cros_ec_query_all()
522 * battery, AC status, and power-state events, because (a) in cros_ec_query_all()
524 * charge, on AC) and (b) these are not actionable wake events; in cros_ec_query_all()
526 * power), not wake up. in cros_ec_query_all()
528 ec_dev->host_event_wake_mask = U32_MAX & in cros_ec_query_all()
538 if (ret != -EOPNOTSUPP) in cros_ec_query_all()
539 dev_err(ec_dev->dev, in cros_ec_query_all()
540 "failed to retrieve wake mask: %d\n", ret); in cros_ec_query_all()
552 * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
561 * >=0 - The number of bytes transferred
562 * <0 - Linux error code
569 mutex_lock(&ec_dev->lock); in cros_ec_cmd_xfer_status()
570 if (ec_dev->proto_version == EC_PROTO_VERSION_UNKNOWN) { in cros_ec_cmd_xfer_status()
573 dev_err(ec_dev->dev, in cros_ec_cmd_xfer_status()
575 mutex_unlock(&ec_dev->lock); in cros_ec_cmd_xfer_status()
580 if (msg->insize > ec_dev->max_response) { in cros_ec_cmd_xfer_status()
581 dev_dbg(ec_dev->dev, "clamping message receive buffer\n"); in cros_ec_cmd_xfer_status()
582 msg->insize = ec_dev->max_response; in cros_ec_cmd_xfer_status()
585 if (msg->command < EC_CMD_PASSTHRU_OFFSET(1)) { in cros_ec_cmd_xfer_status()
586 if (msg->outsize > ec_dev->max_request) { in cros_ec_cmd_xfer_status()
587 dev_err(ec_dev->dev, in cros_ec_cmd_xfer_status()
589 msg->outsize, in cros_ec_cmd_xfer_status()
590 ec_dev->max_request); in cros_ec_cmd_xfer_status()
591 mutex_unlock(&ec_dev->lock); in cros_ec_cmd_xfer_status()
592 return -EMSGSIZE; in cros_ec_cmd_xfer_status()
595 if (msg->outsize > ec_dev->max_passthru) { in cros_ec_cmd_xfer_status()
596 dev_err(ec_dev->dev, in cros_ec_cmd_xfer_status()
598 msg->outsize, in cros_ec_cmd_xfer_status()
599 ec_dev->max_passthru); in cros_ec_cmd_xfer_status()
600 mutex_unlock(&ec_dev->lock); in cros_ec_cmd_xfer_status()
601 return -EMSGSIZE; in cros_ec_cmd_xfer_status()
606 mutex_unlock(&ec_dev->lock); in cros_ec_cmd_xfer_status()
608 mapped = cros_ec_map_error(msg->result); in cros_ec_cmd_xfer_status()
610 dev_dbg(ec_dev->dev, "Command result (err: %d [%d])\n", in cros_ec_cmd_xfer_status()
611 msg->result, mapped); in cros_ec_cmd_xfer_status()
626 msg->version = version; in get_next_event_xfer()
627 msg->command = EC_CMD_GET_NEXT_EVENT; in get_next_event_xfer()
628 msg->insize = size; in get_next_event_xfer()
629 msg->outsize = 0; in get_next_event_xfer()
633 ec_dev->event_size = ret - 1; in get_next_event_xfer()
634 ec_dev->event_data = *event; in get_next_event_xfer()
648 const int cmd_version = ec_dev->mkbp_event_supported - 1; in get_next_event()
651 if (ec_dev->suspended) { in get_next_event()
652 dev_dbg(ec_dev->dev, "Device suspended.\n"); in get_next_event()
653 return -EHOSTDOWN; in get_next_event()
667 sizeof(ec_dev->event_data.data)]; in get_keyboard_state_event()
670 msg->version = 0; in get_keyboard_state_event()
671 msg->command = EC_CMD_MKBP_STATE; in get_keyboard_state_event()
672 msg->insize = sizeof(ec_dev->event_data.data); in get_keyboard_state_event()
673 msg->outsize = 0; in get_keyboard_state_event()
675 ec_dev->event_size = cros_ec_cmd_xfer_status(ec_dev, msg); in get_keyboard_state_event()
676 ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX; in get_keyboard_state_event()
677 memcpy(&ec_dev->event_data.data, msg->data, in get_keyboard_state_event()
678 sizeof(ec_dev->event_data.data)); in get_keyboard_state_event()
680 return ec_dev->event_size; in get_keyboard_state_event()
684 * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
687 * treated as a wake event. Ignored if null.
699 * written out to @ec_dev->event_data.event_type on success.
711 * Wake up on keyboard event, wake up for spurious interrupt or link in cros_ec_get_next_event()
725 if (!ec_dev->mkbp_event_supported) in cros_ec_get_next_event()
733 *has_more_events = ec_dev->event_data.event_type & in cros_ec_get_next_event()
735 ec_dev->event_data.event_type &= EC_MKBP_EVENT_TYPE_MASK; in cros_ec_get_next_event()
738 event_type = ec_dev->event_data.event_type; in cros_ec_get_next_event()
742 * Sensor events need to be parsed by the sensor sub-device. in cros_ec_get_next_event()
747 /* Masked host-events should not count as wake events. */ in cros_ec_get_next_event()
749 !(host_event & ec_dev->host_event_wake_mask)) in cros_ec_get_next_event()
758 * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
765 * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
771 BUG_ON(!ec_dev->mkbp_event_supported); in cros_ec_get_host_event()
773 if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT) in cros_ec_get_host_event()
776 if (ec_dev->event_size != sizeof(host_event)) { in cros_ec_get_host_event()
777 dev_warn(ec_dev->dev, "Invalid host event size\n"); in cros_ec_get_host_event()
781 host_event = get_unaligned_le32(&ec_dev->event_data.data.host_event); in cros_ec_get_host_event()
788 * cros_ec_check_features() - Test for the presence of EC features
803 if (ec->features[0] == -1U && ec->features[1] == -1U) { in cros_ec_check_features()
805 msg = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL); in cros_ec_check_features()
807 return -ENOMEM; in cros_ec_check_features()
809 msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset; in cros_ec_check_features()
810 msg->insize = sizeof(ec->features); in cros_ec_check_features()
812 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); in cros_ec_check_features()
814 dev_warn(ec->dev, "cannot get EC features: %d/%d\n", in cros_ec_check_features()
815 ret, msg->result); in cros_ec_check_features()
816 memset(ec->features, 0, sizeof(ec->features)); in cros_ec_check_features()
818 memcpy(ec->features, msg->data, sizeof(ec->features)); in cros_ec_check_features()
821 dev_dbg(ec->dev, "EC features %08x %08x\n", in cros_ec_check_features()
822 ec->features[0], ec->features[1]); in cros_ec_check_features()
827 return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature); in cros_ec_check_features()
832 * cros_ec_get_sensor_count() - Return the number of MEMS sensors supported.
848 struct cros_ec_device *ec_dev = ec->ec_dev; in cros_ec_get_sensor_count()
854 return -ENOMEM; in cros_ec_get_sensor_count()
856 msg->version = 1; in cros_ec_get_sensor_count()
857 msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; in cros_ec_get_sensor_count()
858 msg->outsize = sizeof(*params); in cros_ec_get_sensor_count()
859 msg->insize = sizeof(*resp); in cros_ec_get_sensor_count()
861 params = (struct ec_params_motion_sense *)msg->data; in cros_ec_get_sensor_count()
862 params->cmd = MOTIONSENSE_CMD_DUMP; in cros_ec_get_sensor_count()
864 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); in cros_ec_get_sensor_count()
868 resp = (struct ec_response_motion_sense *)msg->data; in cros_ec_get_sensor_count()
869 sensor_count = resp->dump.sensor_count; in cros_ec_get_sensor_count()
877 if (sensor_count < 0 && ec->cmd_offset == 0 && ec_dev->cmd_readmem) { in cros_ec_get_sensor_count()
878 ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, in cros_ec_get_sensor_count()