Lines Matching +full:sensors +full:- +full:mems
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 if (msg->outsize + sizeof(*request) > ec_dev->dout_size) in prepare_tx()
64 return -EINVAL; in prepare_tx()
66 out = ec_dev->dout; in prepare_tx()
68 request->struct_version = EC_HOST_REQUEST_VERSION; in prepare_tx()
69 request->checksum = 0; in prepare_tx()
70 request->command = msg->command; in prepare_tx()
71 request->command_version = msg->version; in prepare_tx()
72 request->reserved = 0; in prepare_tx()
73 request->data_len = msg->outsize; in prepare_tx()
79 memcpy(out + sizeof(*request), msg->data, msg->outsize); in prepare_tx()
80 for (i = 0; i < msg->outsize; i++) in prepare_tx()
81 csum += msg->data[i]; in prepare_tx()
83 request->checksum = -csum; in prepare_tx()
85 return sizeof(*request) + msg->outsize; in prepare_tx()
95 if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE) in prepare_tx_legacy()
96 return -EINVAL; in prepare_tx_legacy()
98 out = ec_dev->dout; in prepare_tx_legacy()
99 out[0] = EC_CMD_VERSION0 + msg->version; in prepare_tx_legacy()
100 out[1] = msg->command; in prepare_tx_legacy()
101 out[2] = msg->outsize; in prepare_tx_legacy()
103 for (i = 0; i < msg->outsize; i++) in prepare_tx_legacy()
104 csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->data[i]; in prepare_tx_legacy()
105 out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = csum; in prepare_tx_legacy()
107 return EC_MSG_TX_PROTO_BYTES + msg->outsize; in prepare_tx_legacy()
115 if (ec_dev->proto_version > 2) in cros_ec_xfer_command()
116 xfer_fxn = ec_dev->pkt_xfer; in cros_ec_xfer_command()
118 xfer_fxn = ec_dev->cmd_xfer; in cros_ec_xfer_command()
126 dev_err_once(ec_dev->dev, "missing EC transfer API, cannot send command\n"); in cros_ec_xfer_command()
127 return -EIO; in cros_ec_xfer_command()
147 msg->version = 0; in cros_ec_wait_until_complete()
148 msg->command = EC_CMD_GET_COMMS_STATUS; in cros_ec_wait_until_complete()
149 msg->insize = sizeof(*status); in cros_ec_wait_until_complete()
150 msg->outsize = 0; in cros_ec_wait_until_complete()
157 if (ret == -EAGAIN) in cros_ec_wait_until_complete()
162 *result = msg->result; in cros_ec_wait_until_complete()
163 if (msg->result != EC_RES_SUCCESS) in cros_ec_wait_until_complete()
167 ret = -EPROTO; in cros_ec_wait_until_complete()
171 if (!(status->flags & EC_COMMS_STATUS_PROCESSING)) in cros_ec_wait_until_complete()
176 ret = -EAGAIN; in cros_ec_wait_until_complete()
185 if (msg->result == EC_RES_IN_PROGRESS) in cros_ec_send_command()
186 ret = cros_ec_wait_until_complete(ec_dev, &msg->result); in cros_ec_send_command()
192 * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
204 if (ec_dev->proto_version > 2) in cros_ec_prepare_tx()
212 * cros_ec_check_result() - Check ec_msg->result.
216 * This is used by ChromeOS EC drivers to check the ec_msg->result for
222 * Return: -EAGAIN if ec_msg->result == EC_RES_IN_PROGRESS. Otherwise, 0.
227 switch (msg->result) { in cros_ec_check_result()
231 dev_dbg(ec_dev->dev, "command 0x%02x in progress\n", in cros_ec_check_result()
232 msg->command); in cros_ec_check_result()
233 return -EAGAIN; in cros_ec_check_result()
235 dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n", in cros_ec_check_result()
236 msg->command, msg->result); in cros_ec_check_result()
252 * the caller has ec_dev->lock mutex, or the caller knows there is
263 return -ENOMEM; in cros_ec_get_host_event_wake_mask()
265 msg->command = EC_CMD_HOST_EVENT_GET_WAKE_MASK; in cros_ec_get_host_event_wake_mask()
266 msg->insize = sizeof(*r); in cros_ec_get_host_event_wake_mask()
272 mapped = cros_ec_map_error(msg->result); in cros_ec_get_host_event_wake_mask()
279 ret = -EPROTO; in cros_ec_get_host_event_wake_mask()
283 r = (struct ec_response_host_event_mask *)msg->data; in cros_ec_get_host_event_wake_mask()
284 *mask = r->mask; in cros_ec_get_host_event_wake_mask()
297 ec_dev->proto_version = 3; in cros_ec_get_proto_info()
299 ec_dev->max_passthru = 0; in cros_ec_get_proto_info()
303 return -ENOMEM; in cros_ec_get_proto_info()
305 msg->command = EC_CMD_PASSTHRU_OFFSET(devidx) | EC_CMD_GET_PROTOCOL_INFO; in cros_ec_get_proto_info()
306 msg->insize = sizeof(*info); in cros_ec_get_proto_info()
316 if (ret == -ETIMEDOUT) in cros_ec_get_proto_info()
320 dev_dbg(ec_dev->dev, in cros_ec_get_proto_info()
326 mapped = cros_ec_map_error(msg->result); in cros_ec_get_proto_info()
333 ret = -EPROTO; in cros_ec_get_proto_info()
337 info = (struct ec_response_get_protocol_info *)msg->data; in cros_ec_get_proto_info()
341 ec_dev->max_request = info->max_request_packet_size - in cros_ec_get_proto_info()
343 ec_dev->max_response = info->max_response_packet_size - in cros_ec_get_proto_info()
345 ec_dev->proto_version = min(EC_HOST_REQUEST_VERSION, in cros_ec_get_proto_info()
346 fls(info->protocol_versions) - 1); in cros_ec_get_proto_info()
347 ec_dev->din_size = info->max_response_packet_size + EC_MAX_RESPONSE_OVERHEAD; in cros_ec_get_proto_info()
348 ec_dev->dout_size = info->max_request_packet_size + EC_MAX_REQUEST_OVERHEAD; in cros_ec_get_proto_info()
350 dev_dbg(ec_dev->dev, "using proto v%u\n", ec_dev->proto_version); in cros_ec_get_proto_info()
353 ec_dev->max_passthru = info->max_request_packet_size - in cros_ec_get_proto_info()
356 dev_dbg(ec_dev->dev, "found PD chip\n"); in cros_ec_get_proto_info()
359 dev_dbg(ec_dev->dev, "unknown passthru index: %d\n", devidx); in cros_ec_get_proto_info()
376 ec_dev->proto_version = 2; in cros_ec_get_proto_info_legacy()
380 return -ENOMEM; in cros_ec_get_proto_info_legacy()
382 msg->command = EC_CMD_HELLO; in cros_ec_get_proto_info_legacy()
383 msg->insize = sizeof(*response); in cros_ec_get_proto_info_legacy()
384 msg->outsize = sizeof(*params); in cros_ec_get_proto_info_legacy()
386 params = (struct ec_params_hello *)msg->data; in cros_ec_get_proto_info_legacy()
387 params->in_data = 0xa0b0c0d0; in cros_ec_get_proto_info_legacy()
391 dev_dbg(ec_dev->dev, "EC failed to respond to v2 hello: %d\n", ret); in cros_ec_get_proto_info_legacy()
395 mapped = cros_ec_map_error(msg->result); in cros_ec_get_proto_info_legacy()
398 dev_err(ec_dev->dev, "EC responded to v2 hello with error: %d\n", msg->result); in cros_ec_get_proto_info_legacy()
403 ret = -EPROTO; in cros_ec_get_proto_info_legacy()
407 response = (struct ec_response_hello *)msg->data; in cros_ec_get_proto_info_legacy()
408 if (response->out_data != 0xa1b2c3d4) { in cros_ec_get_proto_info_legacy()
409 dev_err(ec_dev->dev, in cros_ec_get_proto_info_legacy()
411 response->out_data); in cros_ec_get_proto_info_legacy()
412 ret = -EBADMSG; in cros_ec_get_proto_info_legacy()
416 ec_dev->max_request = EC_PROTO2_MAX_PARAM_SIZE; in cros_ec_get_proto_info_legacy()
417 ec_dev->max_response = EC_PROTO2_MAX_PARAM_SIZE; in cros_ec_get_proto_info_legacy()
418 ec_dev->max_passthru = 0; in cros_ec_get_proto_info_legacy()
419 ec_dev->pkt_xfer = NULL; in cros_ec_get_proto_info_legacy()
420 ec_dev->din_size = EC_PROTO2_MSG_BYTES; in cros_ec_get_proto_info_legacy()
421 ec_dev->dout_size = EC_PROTO2_MSG_BYTES; in cros_ec_get_proto_info_legacy()
423 dev_dbg(ec_dev->dev, "falling back to proto v2\n"); in cros_ec_get_proto_info_legacy()
443 * the caller has ec_dev->lock mutex or the caller knows there is
456 return -ENOMEM; in cros_ec_get_host_command_version_mask()
458 msg->version = 0; in cros_ec_get_host_command_version_mask()
459 msg->command = EC_CMD_GET_CMD_VERSIONS; in cros_ec_get_host_command_version_mask()
460 msg->insize = sizeof(*rver); in cros_ec_get_host_command_version_mask()
461 msg->outsize = sizeof(*pver); in cros_ec_get_host_command_version_mask()
463 pver = (struct ec_params_get_cmd_versions *)msg->data; in cros_ec_get_host_command_version_mask()
464 pver->cmd = cmd; in cros_ec_get_host_command_version_mask()
470 mapped = cros_ec_map_error(msg->result); in cros_ec_get_host_command_version_mask()
477 ret = -EPROTO; in cros_ec_get_host_command_version_mask()
481 rver = (struct ec_response_get_cmd_versions *)msg->data; in cros_ec_get_host_command_version_mask()
482 *mask = rver->version_mask; in cros_ec_get_host_command_version_mask()
490 * cros_ec_query_all() - Query the protocol version supported by the
498 struct device *dev = ec_dev->dev; in cros_ec_query_all()
515 ec_dev->proto_version = EC_PROTO_VERSION_UNKNOWN; in cros_ec_query_all()
516 dev_dbg(ec_dev->dev, "EC query failed: %d\n", ret); in cros_ec_query_all()
521 devm_kfree(dev, ec_dev->din); in cros_ec_query_all()
522 devm_kfree(dev, ec_dev->dout); in cros_ec_query_all()
524 ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL); in cros_ec_query_all()
525 if (!ec_dev->din) { in cros_ec_query_all()
526 ret = -ENOMEM; in cros_ec_query_all()
530 ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL); in cros_ec_query_all()
531 if (!ec_dev->dout) { in cros_ec_query_all()
532 devm_kfree(dev, ec_dev->din); in cros_ec_query_all()
533 ret = -ENOMEM; in cros_ec_query_all()
540 ec_dev->mkbp_event_supported = 0; in cros_ec_query_all()
542 ec_dev->mkbp_event_supported = fls(ver_mask); in cros_ec_query_all()
544 dev_dbg(ec_dev->dev, "MKBP support version %u\n", ec_dev->mkbp_event_supported - 1); in cros_ec_query_all()
549 ec_dev->host_sleep_v1 = (ret == 0 && (ver_mask & EC_VER_MASK(1))); in cros_ec_query_all()
552 ret = cros_ec_get_host_event_wake_mask(ec_dev, &ec_dev->host_event_wake_mask); in cros_ec_query_all()
557 * battery, AC status, and power-state events, because (a) in cros_ec_query_all()
563 ec_dev->host_event_wake_mask = U32_MAX & in cros_ec_query_all()
575 if (ret != -EOPNOTSUPP) in cros_ec_query_all()
576 dev_err(ec_dev->dev, in cros_ec_query_all()
588 * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
595 * in-kernel users will want to use cros_ec_cmd_xfer_status() instead since
599 * >0 - EC command was executed successfully. The return value is the number
601 * =0 - EC communication was successful. EC command execution results are
602 * reported in msg->result. The result will be EC_RES_SUCCESS if the
605 * <0 - EC communication error. Return value is the Linux error code.
611 mutex_lock(&ec_dev->lock); in cros_ec_cmd_xfer()
612 if (ec_dev->proto_version == EC_PROTO_VERSION_UNKNOWN) { in cros_ec_cmd_xfer()
615 dev_err(ec_dev->dev, in cros_ec_cmd_xfer()
617 mutex_unlock(&ec_dev->lock); in cros_ec_cmd_xfer()
622 if (msg->insize > ec_dev->max_response) { in cros_ec_cmd_xfer()
623 dev_dbg(ec_dev->dev, "clamping message receive buffer\n"); in cros_ec_cmd_xfer()
624 msg->insize = ec_dev->max_response; in cros_ec_cmd_xfer()
627 if (msg->command < EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX)) { in cros_ec_cmd_xfer()
628 if (msg->outsize > ec_dev->max_request) { in cros_ec_cmd_xfer()
629 dev_err(ec_dev->dev, in cros_ec_cmd_xfer()
631 msg->outsize, in cros_ec_cmd_xfer()
632 ec_dev->max_request); in cros_ec_cmd_xfer()
633 mutex_unlock(&ec_dev->lock); in cros_ec_cmd_xfer()
634 return -EMSGSIZE; in cros_ec_cmd_xfer()
637 if (msg->outsize > ec_dev->max_passthru) { in cros_ec_cmd_xfer()
638 dev_err(ec_dev->dev, in cros_ec_cmd_xfer()
640 msg->outsize, in cros_ec_cmd_xfer()
641 ec_dev->max_passthru); in cros_ec_cmd_xfer()
642 mutex_unlock(&ec_dev->lock); in cros_ec_cmd_xfer()
643 return -EMSGSIZE; in cros_ec_cmd_xfer()
648 mutex_unlock(&ec_dev->lock); in cros_ec_cmd_xfer()
655 * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
664 * >=0 - The number of bytes transferred.
665 * <0 - Linux error code
676 mapped = cros_ec_map_error(msg->result); in cros_ec_cmd_xfer_status()
678 dev_dbg(ec_dev->dev, "Command result (err: %d [%d])\n", in cros_ec_cmd_xfer_status()
679 msg->result, mapped); in cros_ec_cmd_xfer_status()
694 msg->version = version; in get_next_event_xfer()
695 msg->command = EC_CMD_GET_NEXT_EVENT; in get_next_event_xfer()
696 msg->insize = size; in get_next_event_xfer()
697 msg->outsize = 0; in get_next_event_xfer()
701 ec_dev->event_size = ret - 1; in get_next_event_xfer()
702 ec_dev->event_data = *event; in get_next_event_xfer()
716 const int cmd_version = ec_dev->mkbp_event_supported - 1; in get_next_event()
719 if (ec_dev->suspended) { in get_next_event()
720 dev_dbg(ec_dev->dev, "Device suspended.\n"); in get_next_event()
721 return -EHOSTDOWN; in get_next_event()
735 sizeof(ec_dev->event_data.data)]; in get_keyboard_state_event()
738 msg->version = 0; in get_keyboard_state_event()
739 msg->command = EC_CMD_MKBP_STATE; in get_keyboard_state_event()
740 msg->insize = sizeof(ec_dev->event_data.data); in get_keyboard_state_event()
741 msg->outsize = 0; in get_keyboard_state_event()
743 ec_dev->event_size = cros_ec_cmd_xfer_status(ec_dev, msg); in get_keyboard_state_event()
744 ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX; in get_keyboard_state_event()
745 memcpy(&ec_dev->event_data.data, msg->data, in get_keyboard_state_event()
746 sizeof(ec_dev->event_data.data)); in get_keyboard_state_event()
748 return ec_dev->event_size; in get_keyboard_state_event()
752 * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
767 * written out to @ec_dev->event_data.event_type on success.
794 if (!ec_dev->mkbp_event_supported) in cros_ec_get_next_event()
799 * -ENOPROTOOPT is returned when EC returns EC_RES_INVALID_VERSION. in cros_ec_get_next_event()
805 if (ret == -ENOPROTOOPT) { in cros_ec_get_next_event()
806 dev_dbg(ec_dev->dev, in cros_ec_get_next_event()
808 mutex_lock(&ec_dev->lock); in cros_ec_get_next_event()
812 mutex_unlock(&ec_dev->lock); in cros_ec_get_next_event()
821 return -ENOPROTOOPT; in cros_ec_get_next_event()
823 ec_dev->mkbp_event_supported = fls(ver_mask); in cros_ec_get_next_event()
824 dev_dbg(ec_dev->dev, "MKBP support version changed to %u\n", in cros_ec_get_next_event()
825 ec_dev->mkbp_event_supported - 1); in cros_ec_get_next_event()
835 *has_more_events = ec_dev->event_data.event_type & in cros_ec_get_next_event()
837 ec_dev->event_data.event_type &= EC_MKBP_EVENT_TYPE_MASK; in cros_ec_get_next_event()
840 event_type = ec_dev->event_data.event_type; in cros_ec_get_next_event()
844 * Sensor events need to be parsed by the sensor sub-device. in cros_ec_get_next_event()
853 /* Masked host-events should not count as wake events. */ in cros_ec_get_next_event()
854 if (!(host_event & ec_dev->host_event_wake_mask)) in cros_ec_get_next_event()
864 * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
871 * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
877 if (!ec_dev->mkbp_event_supported) in cros_ec_get_host_event()
880 if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT) in cros_ec_get_host_event()
883 if (ec_dev->event_size != sizeof(host_event)) { in cros_ec_get_host_event()
884 dev_warn(ec_dev->dev, "Invalid host event size\n"); in cros_ec_get_host_event()
888 host_event = get_unaligned_le32(&ec_dev->event_data.data.host_event); in cros_ec_get_host_event()
895 * cros_ec_check_features() - Test for the presence of EC features
907 struct ec_response_get_features *features = &ec->features; in cros_ec_check_features()
910 if (features->flags[0] == -1U && features->flags[1] == -1U) { in cros_ec_check_features()
912 ret = cros_ec_cmd(ec->ec_dev, 0, EC_CMD_GET_FEATURES + ec->cmd_offset, in cros_ec_check_features()
915 dev_warn(ec->dev, "cannot get EC features: %d\n", ret); in cros_ec_check_features()
919 dev_dbg(ec->dev, "EC features %08x %08x\n", in cros_ec_check_features()
920 features->flags[0], features->flags[1]); in cros_ec_check_features()
923 return !!(features->flags[feature / 32] & EC_FEATURE_MASK_0(feature)); in cros_ec_check_features()
928 * cros_ec_get_sensor_count() - Return the number of MEMS sensors supported.
944 struct cros_ec_device *ec_dev = ec->ec_dev; in cros_ec_get_sensor_count()
950 return -ENOMEM; in cros_ec_get_sensor_count()
952 msg->version = 1; in cros_ec_get_sensor_count()
953 msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset; in cros_ec_get_sensor_count()
954 msg->outsize = sizeof(*params); in cros_ec_get_sensor_count()
955 msg->insize = sizeof(*resp); in cros_ec_get_sensor_count()
957 params = (struct ec_params_motion_sense *)msg->data; in cros_ec_get_sensor_count()
958 params->cmd = MOTIONSENSE_CMD_DUMP; in cros_ec_get_sensor_count()
960 ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg); in cros_ec_get_sensor_count()
964 resp = (struct ec_response_motion_sense *)msg->data; in cros_ec_get_sensor_count()
965 sensor_count = resp->dump.sensor_count; in cros_ec_get_sensor_count()
970 * Check legacy mode: Let's find out if sensors are accessible in cros_ec_get_sensor_count()
973 if (sensor_count < 0 && ec->cmd_offset == 0 && ec_dev->cmd_readmem) { in cros_ec_get_sensor_count()
974 ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS, in cros_ec_get_sensor_count()
979 * We have 2 sensors, one in the lid, one in the base. in cros_ec_get_sensor_count()
984 * EC uses LPC interface and no sensors are presented. in cros_ec_get_sensor_count()
994 * cros_ec_cmd - Send a command to the EC.
1019 return -ENOMEM; in cros_ec_cmd()
1021 msg->version = version; in cros_ec_cmd()
1022 msg->command = command; in cros_ec_cmd()
1023 msg->outsize = outsize; in cros_ec_cmd()
1024 msg->insize = insize; in cros_ec_cmd()
1027 memcpy(msg->data, outdata, outsize); in cros_ec_cmd()
1034 memcpy(indata, msg->data, insize); in cros_ec_cmd()