1 // SPDX-License-Identifier: GPL-2.0
2 // ChromeOS EC communication protocol helper functions
4 // Copyright (C) 2015 Google, Inc
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>
14 #include "cros_ec_trace.h"
16 #define EC_COMMAND_RETRIES 50
18 static const int cros_ec_error_map
[] = {
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
,
41 static int cros_ec_map_error(uint32_t result
)
45 if (result
!= EC_RES_SUCCESS
) {
46 if (result
< ARRAY_SIZE(cros_ec_error_map
) && cros_ec_error_map
[result
])
47 ret
= cros_ec_error_map
[result
];
55 static int prepare_packet(struct cros_ec_device
*ec_dev
,
56 struct cros_ec_command
*msg
)
58 struct ec_host_request
*request
;
63 BUG_ON(ec_dev
->proto_version
!= EC_HOST_REQUEST_VERSION
);
64 BUG_ON(msg
->outsize
+ sizeof(*request
) > ec_dev
->dout_size
);
67 request
= (struct ec_host_request
*)out
;
68 request
->struct_version
= EC_HOST_REQUEST_VERSION
;
69 request
->checksum
= 0;
70 request
->command
= msg
->command
;
71 request
->command_version
= msg
->version
;
72 request
->reserved
= 0;
73 request
->data_len
= msg
->outsize
;
75 for (i
= 0; i
< sizeof(*request
); i
++)
78 /* Copy data and update checksum */
79 memcpy(out
+ sizeof(*request
), msg
->data
, msg
->outsize
);
80 for (i
= 0; i
< msg
->outsize
; i
++)
83 request
->checksum
= -csum
;
85 return sizeof(*request
) + msg
->outsize
;
88 static int send_command(struct cros_ec_device
*ec_dev
,
89 struct cros_ec_command
*msg
)
92 int (*xfer_fxn
)(struct cros_ec_device
*ec
, struct cros_ec_command
*msg
);
94 if (ec_dev
->proto_version
> 2)
95 xfer_fxn
= ec_dev
->pkt_xfer
;
97 xfer_fxn
= ec_dev
->cmd_xfer
;
101 * This error can happen if a communication error happened and
102 * the EC is trying to use protocol v2, on an underlying
103 * communication mechanism that does not support v2.
105 dev_err_once(ec_dev
->dev
,
106 "missing EC transfer API, cannot send command\n");
110 trace_cros_ec_request_start(msg
);
111 ret
= (*xfer_fxn
)(ec_dev
, msg
);
112 trace_cros_ec_request_done(msg
, ret
);
113 if (msg
->result
== EC_RES_IN_PROGRESS
) {
115 struct cros_ec_command
*status_msg
;
116 struct ec_response_get_comms_status
*status
;
118 status_msg
= kmalloc(sizeof(*status_msg
) + sizeof(*status
),
123 status_msg
->version
= 0;
124 status_msg
->command
= EC_CMD_GET_COMMS_STATUS
;
125 status_msg
->insize
= sizeof(*status
);
126 status_msg
->outsize
= 0;
129 * Query the EC's status until it's no longer busy or
130 * we encounter an error.
132 for (i
= 0; i
< EC_COMMAND_RETRIES
; i
++) {
133 usleep_range(10000, 11000);
135 trace_cros_ec_request_start(status_msg
);
136 ret
= (*xfer_fxn
)(ec_dev
, status_msg
);
137 trace_cros_ec_request_done(status_msg
, ret
);
143 msg
->result
= status_msg
->result
;
144 if (status_msg
->result
!= EC_RES_SUCCESS
)
147 status
= (struct ec_response_get_comms_status
*)
149 if (!(status
->flags
& EC_COMMS_STATUS_PROCESSING
))
160 * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
161 * @ec_dev: Device to register.
162 * @msg: Message to write.
164 * This is intended to be used by all ChromeOS EC drivers, but at present
165 * only SPI uses it. Once LPC uses the same protocol it can start using it.
166 * I2C could use it now, with a refactor of the existing code.
168 * Return: 0 on success or negative error code.
170 int cros_ec_prepare_tx(struct cros_ec_device
*ec_dev
,
171 struct cros_ec_command
*msg
)
177 if (ec_dev
->proto_version
> 2)
178 return prepare_packet(ec_dev
, msg
);
180 BUG_ON(msg
->outsize
> EC_PROTO2_MAX_PARAM_SIZE
);
182 out
[0] = EC_CMD_VERSION0
+ msg
->version
;
183 out
[1] = msg
->command
;
184 out
[2] = msg
->outsize
;
185 csum
= out
[0] + out
[1] + out
[2];
186 for (i
= 0; i
< msg
->outsize
; i
++)
187 csum
+= out
[EC_MSG_TX_HEADER_BYTES
+ i
] = msg
->data
[i
];
188 out
[EC_MSG_TX_HEADER_BYTES
+ msg
->outsize
] = csum
;
190 return EC_MSG_TX_PROTO_BYTES
+ msg
->outsize
;
192 EXPORT_SYMBOL(cros_ec_prepare_tx
);
195 * cros_ec_check_result() - Check ec_msg->result.
196 * @ec_dev: EC device.
197 * @msg: Message to check.
199 * This is used by ChromeOS EC drivers to check the ec_msg->result for
200 * errors and to warn about them.
202 * Return: 0 on success or negative error code.
204 int cros_ec_check_result(struct cros_ec_device
*ec_dev
,
205 struct cros_ec_command
*msg
)
207 switch (msg
->result
) {
210 case EC_RES_IN_PROGRESS
:
211 dev_dbg(ec_dev
->dev
, "command 0x%02x in progress\n",
215 dev_dbg(ec_dev
->dev
, "command 0x%02x returned %d\n",
216 msg
->command
, msg
->result
);
220 EXPORT_SYMBOL(cros_ec_check_result
);
223 * cros_ec_get_host_event_wake_mask
225 * Get the mask of host events that cause wake from suspend.
227 * @ec_dev: EC device to call
228 * @msg: message structure to use
229 * @mask: result when function returns >=0.
232 * the caller has ec_dev->lock mutex, or the caller knows there is
233 * no other command in progress.
235 static int cros_ec_get_host_event_wake_mask(struct cros_ec_device
*ec_dev
,
236 struct cros_ec_command
*msg
,
239 struct ec_response_host_event_mask
*r
;
242 msg
->command
= EC_CMD_HOST_EVENT_GET_WAKE_MASK
;
245 msg
->insize
= sizeof(*r
);
247 ret
= send_command(ec_dev
, msg
);
249 if (msg
->result
== EC_RES_INVALID_COMMAND
)
251 if (msg
->result
!= EC_RES_SUCCESS
)
255 r
= (struct ec_response_host_event_mask
*)msg
->data
;
262 static int cros_ec_host_command_proto_query(struct cros_ec_device
*ec_dev
,
264 struct cros_ec_command
*msg
)
267 * Try using v3+ to query for supported protocols. If this
268 * command fails, fall back to v2. Returns the highest protocol
269 * supported by the EC.
270 * Also sets the max request/response/passthru size.
274 if (!ec_dev
->pkt_xfer
)
275 return -EPROTONOSUPPORT
;
277 memset(msg
, 0, sizeof(*msg
));
278 msg
->command
= EC_CMD_PASSTHRU_OFFSET(devidx
) | EC_CMD_GET_PROTOCOL_INFO
;
279 msg
->insize
= sizeof(struct ec_response_get_protocol_info
);
281 ret
= send_command(ec_dev
, msg
);
285 "failed to check for EC[%d] protocol version: %d\n",
290 if (devidx
> 0 && msg
->result
== EC_RES_INVALID_COMMAND
)
292 else if (msg
->result
!= EC_RES_SUCCESS
)
298 static int cros_ec_host_command_proto_query_v2(struct cros_ec_device
*ec_dev
)
300 struct cros_ec_command
*msg
;
301 struct ec_params_hello
*hello_params
;
302 struct ec_response_hello
*hello_response
;
304 int len
= max(sizeof(*hello_params
), sizeof(*hello_response
));
306 msg
= kmalloc(sizeof(*msg
) + len
, GFP_KERNEL
);
311 msg
->command
= EC_CMD_HELLO
;
312 hello_params
= (struct ec_params_hello
*)msg
->data
;
313 msg
->outsize
= sizeof(*hello_params
);
314 hello_response
= (struct ec_response_hello
*)msg
->data
;
315 msg
->insize
= sizeof(*hello_response
);
317 hello_params
->in_data
= 0xa0b0c0d0;
319 ret
= send_command(ec_dev
, msg
);
323 "EC failed to respond to v2 hello: %d\n",
326 } else if (msg
->result
!= EC_RES_SUCCESS
) {
328 "EC responded to v2 hello with error: %d\n",
332 } else if (hello_response
->out_data
!= 0xa1b2c3d4) {
334 "EC responded to v2 hello with bad result: %u\n",
335 hello_response
->out_data
);
348 * cros_ec_get_host_command_version_mask
350 * Get the version mask of a given command.
352 * @ec_dev: EC device to call
353 * @msg: message structure to use
354 * @cmd: command to get the version of.
355 * @mask: result when function returns 0.
357 * @return 0 on success, error code otherwise
360 * the caller has ec_dev->lock mutex or the caller knows there is
361 * no other command in progress.
363 static int cros_ec_get_host_command_version_mask(struct cros_ec_device
*ec_dev
,
366 struct ec_params_get_cmd_versions
*pver
;
367 struct ec_response_get_cmd_versions
*rver
;
368 struct cros_ec_command
*msg
;
371 msg
= kmalloc(sizeof(*msg
) + max(sizeof(*rver
), sizeof(*pver
)),
377 msg
->command
= EC_CMD_GET_CMD_VERSIONS
;
378 msg
->insize
= sizeof(*rver
);
379 msg
->outsize
= sizeof(*pver
);
381 pver
= (struct ec_params_get_cmd_versions
*)msg
->data
;
384 ret
= send_command(ec_dev
, msg
);
386 rver
= (struct ec_response_get_cmd_versions
*)msg
->data
;
387 *mask
= rver
->version_mask
;
396 * cros_ec_query_all() - Query the protocol version supported by the
398 * @ec_dev: Device to register.
400 * Return: 0 on success or negative error code.
402 int cros_ec_query_all(struct cros_ec_device
*ec_dev
)
404 struct device
*dev
= ec_dev
->dev
;
405 struct cros_ec_command
*proto_msg
;
406 struct ec_response_get_protocol_info
*proto_info
;
410 proto_msg
= kzalloc(sizeof(*proto_msg
) + sizeof(*proto_info
),
415 /* First try sending with proto v3. */
416 ec_dev
->proto_version
= 3;
417 ret
= cros_ec_host_command_proto_query(ec_dev
, 0, proto_msg
);
420 proto_info
= (struct ec_response_get_protocol_info
*)
422 ec_dev
->max_request
= proto_info
->max_request_packet_size
-
423 sizeof(struct ec_host_request
);
424 ec_dev
->max_response
= proto_info
->max_response_packet_size
-
425 sizeof(struct ec_host_response
);
426 ec_dev
->proto_version
=
427 min(EC_HOST_REQUEST_VERSION
,
428 fls(proto_info
->protocol_versions
) - 1);
431 ec_dev
->proto_version
);
433 ec_dev
->din_size
= ec_dev
->max_response
+
434 sizeof(struct ec_host_response
) +
435 EC_MAX_RESPONSE_OVERHEAD
;
436 ec_dev
->dout_size
= ec_dev
->max_request
+
437 sizeof(struct ec_host_request
) +
438 EC_MAX_REQUEST_OVERHEAD
;
443 ret
= cros_ec_host_command_proto_query(ec_dev
, 1, proto_msg
);
446 dev_dbg(ec_dev
->dev
, "no PD chip found: %d\n", ret
);
447 ec_dev
->max_passthru
= 0;
449 dev_dbg(ec_dev
->dev
, "found PD chip\n");
450 ec_dev
->max_passthru
=
451 proto_info
->max_request_packet_size
-
452 sizeof(struct ec_host_request
);
455 /* Try querying with a v2 hello message. */
456 ec_dev
->proto_version
= 2;
457 ret
= cros_ec_host_command_proto_query_v2(ec_dev
);
460 /* V2 hello succeeded. */
461 dev_dbg(ec_dev
->dev
, "falling back to proto v2\n");
463 ec_dev
->max_request
= EC_PROTO2_MAX_PARAM_SIZE
;
464 ec_dev
->max_response
= EC_PROTO2_MAX_PARAM_SIZE
;
465 ec_dev
->max_passthru
= 0;
466 ec_dev
->pkt_xfer
= NULL
;
467 ec_dev
->din_size
= EC_PROTO2_MSG_BYTES
;
468 ec_dev
->dout_size
= EC_PROTO2_MSG_BYTES
;
471 * It's possible for a test to occur too early when
472 * the EC isn't listening. If this happens, we'll
473 * test later when the first command is run.
475 ec_dev
->proto_version
= EC_PROTO_VERSION_UNKNOWN
;
476 dev_dbg(ec_dev
->dev
, "EC query failed: %d\n", ret
);
481 devm_kfree(dev
, ec_dev
->din
);
482 devm_kfree(dev
, ec_dev
->dout
);
484 ec_dev
->din
= devm_kzalloc(dev
, ec_dev
->din_size
, GFP_KERNEL
);
490 ec_dev
->dout
= devm_kzalloc(dev
, ec_dev
->dout_size
, GFP_KERNEL
);
492 devm_kfree(dev
, ec_dev
->din
);
497 /* Probe if MKBP event is supported */
498 ret
= cros_ec_get_host_command_version_mask(ec_dev
,
499 EC_CMD_GET_NEXT_EVENT
,
501 if (ret
< 0 || ver_mask
== 0)
502 ec_dev
->mkbp_event_supported
= 0;
504 ec_dev
->mkbp_event_supported
= fls(ver_mask
);
506 dev_dbg(ec_dev
->dev
, "MKBP support version %u\n",
507 ec_dev
->mkbp_event_supported
- 1);
509 /* Probe if host sleep v1 is supported for S0ix failure detection. */
510 ret
= cros_ec_get_host_command_version_mask(ec_dev
,
511 EC_CMD_HOST_SLEEP_EVENT
,
513 ec_dev
->host_sleep_v1
= (ret
>= 0 && (ver_mask
& EC_VER_MASK(1)));
515 /* Get host event wake mask. */
516 ret
= cros_ec_get_host_event_wake_mask(ec_dev
, proto_msg
,
517 &ec_dev
->host_event_wake_mask
);
520 * If the EC doesn't support EC_CMD_HOST_EVENT_GET_WAKE_MASK,
521 * use a reasonable default. Note that we ignore various
522 * battery, AC status, and power-state events, because (a)
523 * those can be quite common (e.g., when sitting at full
524 * charge, on AC) and (b) these are not actionable wake events;
525 * if anything, we'd like to continue suspending (to save
526 * power), not wake up.
528 ec_dev
->host_event_wake_mask
= U32_MAX
&
529 ~(BIT(EC_HOST_EVENT_AC_DISCONNECTED
) |
530 BIT(EC_HOST_EVENT_BATTERY_LOW
) |
531 BIT(EC_HOST_EVENT_BATTERY_CRITICAL
) |
532 BIT(EC_HOST_EVENT_PD_MCU
) |
533 BIT(EC_HOST_EVENT_BATTERY_STATUS
));
535 * Old ECs may not support this command. Complain about all
538 if (ret
!= -EOPNOTSUPP
)
540 "failed to retrieve wake mask: %d\n", ret
);
549 EXPORT_SYMBOL(cros_ec_query_all
);
552 * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
553 * @ec_dev: EC device.
554 * @msg: Message to write.
556 * Call this to send a command to the ChromeOS EC. This should be used instead of calling the EC's
557 * cmd_xfer() callback directly. It returns success status only if both the command was transmitted
558 * successfully and the EC replied with success status.
561 * >=0 - The number of bytes transferred
562 * <0 - Linux error code
564 int cros_ec_cmd_xfer_status(struct cros_ec_device
*ec_dev
,
565 struct cros_ec_command
*msg
)
569 mutex_lock(&ec_dev
->lock
);
570 if (ec_dev
->proto_version
== EC_PROTO_VERSION_UNKNOWN
) {
571 ret
= cros_ec_query_all(ec_dev
);
574 "EC version unknown and query failed; aborting command\n");
575 mutex_unlock(&ec_dev
->lock
);
580 if (msg
->insize
> ec_dev
->max_response
) {
581 dev_dbg(ec_dev
->dev
, "clamping message receive buffer\n");
582 msg
->insize
= ec_dev
->max_response
;
585 if (msg
->command
< EC_CMD_PASSTHRU_OFFSET(1)) {
586 if (msg
->outsize
> ec_dev
->max_request
) {
588 "request of size %u is too big (max: %u)\n",
590 ec_dev
->max_request
);
591 mutex_unlock(&ec_dev
->lock
);
595 if (msg
->outsize
> ec_dev
->max_passthru
) {
597 "passthru rq of size %u is too big (max: %u)\n",
599 ec_dev
->max_passthru
);
600 mutex_unlock(&ec_dev
->lock
);
605 ret
= send_command(ec_dev
, msg
);
606 mutex_unlock(&ec_dev
->lock
);
608 mapped
= cros_ec_map_error(msg
->result
);
610 dev_dbg(ec_dev
->dev
, "Command result (err: %d [%d])\n",
611 msg
->result
, mapped
);
617 EXPORT_SYMBOL(cros_ec_cmd_xfer_status
);
619 static int get_next_event_xfer(struct cros_ec_device
*ec_dev
,
620 struct cros_ec_command
*msg
,
621 struct ec_response_get_next_event_v1
*event
,
622 int version
, uint32_t size
)
626 msg
->version
= version
;
627 msg
->command
= EC_CMD_GET_NEXT_EVENT
;
631 ret
= cros_ec_cmd_xfer_status(ec_dev
, msg
);
633 ec_dev
->event_size
= ret
- 1;
634 ec_dev
->event_data
= *event
;
640 static int get_next_event(struct cros_ec_device
*ec_dev
)
643 struct cros_ec_command msg
;
644 struct ec_response_get_next_event_v1 event
;
646 struct cros_ec_command
*msg
= &buf
.msg
;
647 struct ec_response_get_next_event_v1
*event
= &buf
.event
;
648 const int cmd_version
= ec_dev
->mkbp_event_supported
- 1;
650 memset(msg
, 0, sizeof(*msg
));
651 if (ec_dev
->suspended
) {
652 dev_dbg(ec_dev
->dev
, "Device suspended.\n");
656 if (cmd_version
== 0)
657 return get_next_event_xfer(ec_dev
, msg
, event
, 0,
658 sizeof(struct ec_response_get_next_event
));
660 return get_next_event_xfer(ec_dev
, msg
, event
, cmd_version
,
661 sizeof(struct ec_response_get_next_event_v1
));
664 static int get_keyboard_state_event(struct cros_ec_device
*ec_dev
)
666 u8 buffer
[sizeof(struct cros_ec_command
) +
667 sizeof(ec_dev
->event_data
.data
)];
668 struct cros_ec_command
*msg
= (struct cros_ec_command
*)&buffer
;
671 msg
->command
= EC_CMD_MKBP_STATE
;
672 msg
->insize
= sizeof(ec_dev
->event_data
.data
);
675 ec_dev
->event_size
= cros_ec_cmd_xfer_status(ec_dev
, msg
);
676 ec_dev
->event_data
.event_type
= EC_MKBP_EVENT_KEY_MATRIX
;
677 memcpy(&ec_dev
->event_data
.data
, msg
->data
,
678 sizeof(ec_dev
->event_data
.data
));
680 return ec_dev
->event_size
;
684 * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
685 * @ec_dev: Device to fetch event from.
686 * @wake_event: Pointer to a bool set to true upon return if the event might be
687 * treated as a wake event. Ignored if null.
688 * @has_more_events: Pointer to bool set to true if more than one event is
690 * Some EC will set this flag to indicate cros_ec_get_next_event()
691 * can be called multiple times in a row.
692 * It is an optimization to prevent issuing a EC command for
693 * nothing or wait for another interrupt from the EC to process
697 * Return: negative error code on errors; 0 for no data; or else number of
698 * bytes received (i.e., an event was retrieved successfully). Event types are
699 * written out to @ec_dev->event_data.event_type on success.
701 int cros_ec_get_next_event(struct cros_ec_device
*ec_dev
,
703 bool *has_more_events
)
710 * Default value for wake_event.
711 * Wake up on keyboard event, wake up for spurious interrupt or link
718 * Default value for has_more_events.
719 * EC will raise another interrupt if AP does not process all events
723 *has_more_events
= false;
725 if (!ec_dev
->mkbp_event_supported
)
726 return get_keyboard_state_event(ec_dev
);
728 ret
= get_next_event(ec_dev
);
733 *has_more_events
= ec_dev
->event_data
.event_type
&
734 EC_MKBP_HAS_MORE_EVENTS
;
735 ec_dev
->event_data
.event_type
&= EC_MKBP_EVENT_TYPE_MASK
;
738 event_type
= ec_dev
->event_data
.event_type
;
739 host_event
= cros_ec_get_host_event(ec_dev
);
742 * Sensor events need to be parsed by the sensor sub-device.
743 * Defer them, and don't report the wakeup here.
745 if (event_type
== EC_MKBP_EVENT_SENSOR_FIFO
) {
747 } else if (host_event
) {
748 /* rtc_update_irq() already handles wakeup events. */
749 if (host_event
& EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC
))
751 /* Masked host-events should not count as wake events. */
752 if (!(host_event
& ec_dev
->host_event_wake_mask
))
759 EXPORT_SYMBOL(cros_ec_get_next_event
);
762 * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
763 * @ec_dev: Device to fetch event from.
765 * When MKBP is supported, when the EC raises an interrupt, we collect the
766 * events raised and call the functions in the ec notifier. This function
767 * is a helper to know which events are raised.
769 * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
771 u32
cros_ec_get_host_event(struct cros_ec_device
*ec_dev
)
775 BUG_ON(!ec_dev
->mkbp_event_supported
);
777 if (ec_dev
->event_data
.event_type
!= EC_MKBP_EVENT_HOST_EVENT
)
780 if (ec_dev
->event_size
!= sizeof(host_event
)) {
781 dev_warn(ec_dev
->dev
, "Invalid host event size\n");
785 host_event
= get_unaligned_le32(&ec_dev
->event_data
.data
.host_event
);
789 EXPORT_SYMBOL(cros_ec_get_host_event
);
792 * cros_ec_check_features() - Test for the presence of EC features
794 * @ec: EC device, does not have to be connected directly to the AP,
795 * can be daisy chained through another device.
796 * @feature: One of ec_feature_code bit.
798 * Call this function to test whether the ChromeOS EC supports a feature.
800 * Return: 1 if supported, 0 if not
802 int cros_ec_check_features(struct cros_ec_dev
*ec
, int feature
)
804 struct cros_ec_command
*msg
;
807 if (ec
->features
[0] == -1U && ec
->features
[1] == -1U) {
808 /* features bitmap not read yet */
809 msg
= kzalloc(sizeof(*msg
) + sizeof(ec
->features
), GFP_KERNEL
);
813 msg
->command
= EC_CMD_GET_FEATURES
+ ec
->cmd_offset
;
814 msg
->insize
= sizeof(ec
->features
);
816 ret
= cros_ec_cmd_xfer_status(ec
->ec_dev
, msg
);
818 dev_warn(ec
->dev
, "cannot get EC features: %d/%d\n",
820 memset(ec
->features
, 0, sizeof(ec
->features
));
822 memcpy(ec
->features
, msg
->data
, sizeof(ec
->features
));
825 dev_dbg(ec
->dev
, "EC features %08x %08x\n",
826 ec
->features
[0], ec
->features
[1]);
831 return ec
->features
[feature
/ 32] & EC_FEATURE_MASK_0(feature
);
833 EXPORT_SYMBOL_GPL(cros_ec_check_features
);
836 * cros_ec_get_sensor_count() - Return the number of MEMS sensors supported.
838 * @ec: EC device, does not have to be connected directly to the AP,
839 * can be daisy chained through another device.
840 * Return: < 0 in case of error.
842 int cros_ec_get_sensor_count(struct cros_ec_dev
*ec
)
845 * Issue a command to get the number of sensor reported.
846 * If not supported, check for legacy mode.
848 int ret
, sensor_count
;
849 struct ec_params_motion_sense
*params
;
850 struct ec_response_motion_sense
*resp
;
851 struct cros_ec_command
*msg
;
852 struct cros_ec_device
*ec_dev
= ec
->ec_dev
;
855 msg
= kzalloc(sizeof(*msg
) + max(sizeof(*params
), sizeof(*resp
)),
861 msg
->command
= EC_CMD_MOTION_SENSE_CMD
+ ec
->cmd_offset
;
862 msg
->outsize
= sizeof(*params
);
863 msg
->insize
= sizeof(*resp
);
865 params
= (struct ec_params_motion_sense
*)msg
->data
;
866 params
->cmd
= MOTIONSENSE_CMD_DUMP
;
868 ret
= cros_ec_cmd_xfer_status(ec
->ec_dev
, msg
);
872 resp
= (struct ec_response_motion_sense
*)msg
->data
;
873 sensor_count
= resp
->dump
.sensor_count
;
878 * Check legacy mode: Let's find out if sensors are accessible
881 if (sensor_count
< 0 && ec
->cmd_offset
== 0 && ec_dev
->cmd_readmem
) {
882 ret
= ec_dev
->cmd_readmem(ec_dev
, EC_MEMMAP_ACC_STATUS
,
885 (status
& EC_MEMMAP_ACC_STATUS_PRESENCE_BIT
)) {
887 * We have 2 sensors, one in the lid, one in the base.
892 * EC uses LPC interface and no sensors are presented.
899 EXPORT_SYMBOL_GPL(cros_ec_get_sensor_count
);