2 * ChromeOS EC communication protocol helper functions
4 * Copyright (C) 2015 Google, Inc
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/mfd/cros_ec.h>
18 #include <linux/delay.h>
19 #include <linux/device.h>
20 #include <linux/module.h>
21 #include <linux/slab.h>
22 #include <asm/unaligned.h>
24 #define EC_COMMAND_RETRIES 50
26 static int prepare_packet(struct cros_ec_device
*ec_dev
,
27 struct cros_ec_command
*msg
)
29 struct ec_host_request
*request
;
34 BUG_ON(ec_dev
->proto_version
!= EC_HOST_REQUEST_VERSION
);
35 BUG_ON(msg
->outsize
+ sizeof(*request
) > ec_dev
->dout_size
);
38 request
= (struct ec_host_request
*)out
;
39 request
->struct_version
= EC_HOST_REQUEST_VERSION
;
40 request
->checksum
= 0;
41 request
->command
= msg
->command
;
42 request
->command_version
= msg
->version
;
43 request
->reserved
= 0;
44 request
->data_len
= msg
->outsize
;
46 for (i
= 0; i
< sizeof(*request
); i
++)
49 /* Copy data and update checksum */
50 memcpy(out
+ sizeof(*request
), msg
->data
, msg
->outsize
);
51 for (i
= 0; i
< msg
->outsize
; i
++)
54 request
->checksum
= -csum
;
56 return sizeof(*request
) + msg
->outsize
;
59 static int send_command(struct cros_ec_device
*ec_dev
,
60 struct cros_ec_command
*msg
)
63 int (*xfer_fxn
)(struct cros_ec_device
*ec
, struct cros_ec_command
*msg
);
65 if (ec_dev
->proto_version
> 2)
66 xfer_fxn
= ec_dev
->pkt_xfer
;
68 xfer_fxn
= ec_dev
->cmd_xfer
;
72 * This error can happen if a communication error happened and
73 * the EC is trying to use protocol v2, on an underlying
74 * communication mechanism that does not support v2.
76 dev_err_once(ec_dev
->dev
,
77 "missing EC transfer API, cannot send command\n");
81 ret
= (*xfer_fxn
)(ec_dev
, msg
);
82 if (msg
->result
== EC_RES_IN_PROGRESS
) {
84 struct cros_ec_command
*status_msg
;
85 struct ec_response_get_comms_status
*status
;
87 status_msg
= kmalloc(sizeof(*status_msg
) + sizeof(*status
),
92 status_msg
->version
= 0;
93 status_msg
->command
= EC_CMD_GET_COMMS_STATUS
;
94 status_msg
->insize
= sizeof(*status
);
95 status_msg
->outsize
= 0;
98 * Query the EC's status until it's no longer busy or
99 * we encounter an error.
101 for (i
= 0; i
< EC_COMMAND_RETRIES
; i
++) {
102 usleep_range(10000, 11000);
104 ret
= (*xfer_fxn
)(ec_dev
, status_msg
);
110 msg
->result
= status_msg
->result
;
111 if (status_msg
->result
!= EC_RES_SUCCESS
)
114 status
= (struct ec_response_get_comms_status
*)
116 if (!(status
->flags
& EC_COMMS_STATUS_PROCESSING
))
126 int cros_ec_prepare_tx(struct cros_ec_device
*ec_dev
,
127 struct cros_ec_command
*msg
)
133 if (ec_dev
->proto_version
> 2)
134 return prepare_packet(ec_dev
, msg
);
136 BUG_ON(msg
->outsize
> EC_PROTO2_MAX_PARAM_SIZE
);
138 out
[0] = EC_CMD_VERSION0
+ msg
->version
;
139 out
[1] = msg
->command
;
140 out
[2] = msg
->outsize
;
141 csum
= out
[0] + out
[1] + out
[2];
142 for (i
= 0; i
< msg
->outsize
; i
++)
143 csum
+= out
[EC_MSG_TX_HEADER_BYTES
+ i
] = msg
->data
[i
];
144 out
[EC_MSG_TX_HEADER_BYTES
+ msg
->outsize
] = csum
;
146 return EC_MSG_TX_PROTO_BYTES
+ msg
->outsize
;
148 EXPORT_SYMBOL(cros_ec_prepare_tx
);
150 int cros_ec_check_result(struct cros_ec_device
*ec_dev
,
151 struct cros_ec_command
*msg
)
153 switch (msg
->result
) {
156 case EC_RES_IN_PROGRESS
:
157 dev_dbg(ec_dev
->dev
, "command 0x%02x in progress\n",
161 dev_dbg(ec_dev
->dev
, "command 0x%02x returned %d\n",
162 msg
->command
, msg
->result
);
166 EXPORT_SYMBOL(cros_ec_check_result
);
169 * cros_ec_get_host_event_wake_mask
171 * Get the mask of host events that cause wake from suspend.
173 * @ec_dev: EC device to call
174 * @msg: message structure to use
175 * @mask: result when function returns >=0.
178 * the caller has ec_dev->lock mutex, or the caller knows there is
179 * no other command in progress.
181 static int cros_ec_get_host_event_wake_mask(struct cros_ec_device
*ec_dev
,
182 struct cros_ec_command
*msg
,
185 struct ec_response_host_event_mask
*r
;
188 msg
->command
= EC_CMD_HOST_EVENT_GET_WAKE_MASK
;
191 msg
->insize
= sizeof(*r
);
193 ret
= send_command(ec_dev
, msg
);
195 r
= (struct ec_response_host_event_mask
*)msg
->data
;
202 static int cros_ec_host_command_proto_query(struct cros_ec_device
*ec_dev
,
204 struct cros_ec_command
*msg
)
207 * Try using v3+ to query for supported protocols. If this
208 * command fails, fall back to v2. Returns the highest protocol
209 * supported by the EC.
210 * Also sets the max request/response/passthru size.
214 if (!ec_dev
->pkt_xfer
)
215 return -EPROTONOSUPPORT
;
217 memset(msg
, 0, sizeof(*msg
));
218 msg
->command
= EC_CMD_PASSTHRU_OFFSET(devidx
) | EC_CMD_GET_PROTOCOL_INFO
;
219 msg
->insize
= sizeof(struct ec_response_get_protocol_info
);
221 ret
= send_command(ec_dev
, msg
);
225 "failed to check for EC[%d] protocol version: %d\n",
230 if (devidx
> 0 && msg
->result
== EC_RES_INVALID_COMMAND
)
232 else if (msg
->result
!= EC_RES_SUCCESS
)
238 static int cros_ec_host_command_proto_query_v2(struct cros_ec_device
*ec_dev
)
240 struct cros_ec_command
*msg
;
241 struct ec_params_hello
*hello_params
;
242 struct ec_response_hello
*hello_response
;
244 int len
= max(sizeof(*hello_params
), sizeof(*hello_response
));
246 msg
= kmalloc(sizeof(*msg
) + len
, GFP_KERNEL
);
251 msg
->command
= EC_CMD_HELLO
;
252 hello_params
= (struct ec_params_hello
*)msg
->data
;
253 msg
->outsize
= sizeof(*hello_params
);
254 hello_response
= (struct ec_response_hello
*)msg
->data
;
255 msg
->insize
= sizeof(*hello_response
);
257 hello_params
->in_data
= 0xa0b0c0d0;
259 ret
= send_command(ec_dev
, msg
);
263 "EC failed to respond to v2 hello: %d\n",
266 } else if (msg
->result
!= EC_RES_SUCCESS
) {
268 "EC responded to v2 hello with error: %d\n",
272 } else if (hello_response
->out_data
!= 0xa1b2c3d4) {
274 "EC responded to v2 hello with bad result: %u\n",
275 hello_response
->out_data
);
288 * cros_ec_get_host_command_version_mask
290 * Get the version mask of a given command.
292 * @ec_dev: EC device to call
293 * @msg: message structure to use
294 * @cmd: command to get the version of.
295 * @mask: result when function returns 0.
297 * @return 0 on success, error code otherwise
300 * the caller has ec_dev->lock mutex or the caller knows there is
301 * no other command in progress.
303 static int cros_ec_get_host_command_version_mask(struct cros_ec_device
*ec_dev
,
306 struct ec_params_get_cmd_versions
*pver
;
307 struct ec_response_get_cmd_versions
*rver
;
308 struct cros_ec_command
*msg
;
311 msg
= kmalloc(sizeof(*msg
) + max(sizeof(*rver
), sizeof(*pver
)),
317 msg
->command
= EC_CMD_GET_CMD_VERSIONS
;
318 msg
->insize
= sizeof(*rver
);
319 msg
->outsize
= sizeof(*pver
);
321 pver
= (struct ec_params_get_cmd_versions
*)msg
->data
;
324 ret
= send_command(ec_dev
, msg
);
326 rver
= (struct ec_response_get_cmd_versions
*)msg
->data
;
327 *mask
= rver
->version_mask
;
335 int cros_ec_query_all(struct cros_ec_device
*ec_dev
)
337 struct device
*dev
= ec_dev
->dev
;
338 struct cros_ec_command
*proto_msg
;
339 struct ec_response_get_protocol_info
*proto_info
;
343 proto_msg
= kzalloc(sizeof(*proto_msg
) + sizeof(*proto_info
),
348 /* First try sending with proto v3. */
349 ec_dev
->proto_version
= 3;
350 ret
= cros_ec_host_command_proto_query(ec_dev
, 0, proto_msg
);
353 proto_info
= (struct ec_response_get_protocol_info
*)
355 ec_dev
->max_request
= proto_info
->max_request_packet_size
-
356 sizeof(struct ec_host_request
);
357 ec_dev
->max_response
= proto_info
->max_response_packet_size
-
358 sizeof(struct ec_host_response
);
359 ec_dev
->proto_version
=
360 min(EC_HOST_REQUEST_VERSION
,
361 fls(proto_info
->protocol_versions
) - 1);
364 ec_dev
->proto_version
);
366 ec_dev
->din_size
= ec_dev
->max_response
+
367 sizeof(struct ec_host_response
) +
368 EC_MAX_RESPONSE_OVERHEAD
;
369 ec_dev
->dout_size
= ec_dev
->max_request
+
370 sizeof(struct ec_host_request
) +
371 EC_MAX_REQUEST_OVERHEAD
;
376 ret
= cros_ec_host_command_proto_query(ec_dev
, 1, proto_msg
);
379 dev_dbg(ec_dev
->dev
, "no PD chip found: %d\n", ret
);
380 ec_dev
->max_passthru
= 0;
382 dev_dbg(ec_dev
->dev
, "found PD chip\n");
383 ec_dev
->max_passthru
=
384 proto_info
->max_request_packet_size
-
385 sizeof(struct ec_host_request
);
388 /* Try querying with a v2 hello message. */
389 ec_dev
->proto_version
= 2;
390 ret
= cros_ec_host_command_proto_query_v2(ec_dev
);
393 /* V2 hello succeeded. */
394 dev_dbg(ec_dev
->dev
, "falling back to proto v2\n");
396 ec_dev
->max_request
= EC_PROTO2_MAX_PARAM_SIZE
;
397 ec_dev
->max_response
= EC_PROTO2_MAX_PARAM_SIZE
;
398 ec_dev
->max_passthru
= 0;
399 ec_dev
->pkt_xfer
= NULL
;
400 ec_dev
->din_size
= EC_PROTO2_MSG_BYTES
;
401 ec_dev
->dout_size
= EC_PROTO2_MSG_BYTES
;
404 * It's possible for a test to occur too early when
405 * the EC isn't listening. If this happens, we'll
406 * test later when the first command is run.
408 ec_dev
->proto_version
= EC_PROTO_VERSION_UNKNOWN
;
409 dev_dbg(ec_dev
->dev
, "EC query failed: %d\n", ret
);
414 devm_kfree(dev
, ec_dev
->din
);
415 devm_kfree(dev
, ec_dev
->dout
);
417 ec_dev
->din
= devm_kzalloc(dev
, ec_dev
->din_size
, GFP_KERNEL
);
423 ec_dev
->dout
= devm_kzalloc(dev
, ec_dev
->dout_size
, GFP_KERNEL
);
425 devm_kfree(dev
, ec_dev
->din
);
430 /* Probe if MKBP event is supported */
431 ret
= cros_ec_get_host_command_version_mask(ec_dev
,
432 EC_CMD_GET_NEXT_EVENT
,
434 if (ret
< 0 || ver_mask
== 0)
435 ec_dev
->mkbp_event_supported
= 0;
437 ec_dev
->mkbp_event_supported
= 1;
440 * Get host event wake mask, assume all events are wake events
443 ret
= cros_ec_get_host_event_wake_mask(ec_dev
, proto_msg
,
444 &ec_dev
->host_event_wake_mask
);
446 ec_dev
->host_event_wake_mask
= U32_MAX
;
454 EXPORT_SYMBOL(cros_ec_query_all
);
456 int cros_ec_cmd_xfer(struct cros_ec_device
*ec_dev
,
457 struct cros_ec_command
*msg
)
461 mutex_lock(&ec_dev
->lock
);
462 if (ec_dev
->proto_version
== EC_PROTO_VERSION_UNKNOWN
) {
463 ret
= cros_ec_query_all(ec_dev
);
466 "EC version unknown and query failed; aborting command\n");
467 mutex_unlock(&ec_dev
->lock
);
472 if (msg
->insize
> ec_dev
->max_response
) {
473 dev_dbg(ec_dev
->dev
, "clamping message receive buffer\n");
474 msg
->insize
= ec_dev
->max_response
;
477 if (msg
->command
< EC_CMD_PASSTHRU_OFFSET(1)) {
478 if (msg
->outsize
> ec_dev
->max_request
) {
480 "request of size %u is too big (max: %u)\n",
482 ec_dev
->max_request
);
483 mutex_unlock(&ec_dev
->lock
);
487 if (msg
->outsize
> ec_dev
->max_passthru
) {
489 "passthru rq of size %u is too big (max: %u)\n",
491 ec_dev
->max_passthru
);
492 mutex_unlock(&ec_dev
->lock
);
496 ret
= send_command(ec_dev
, msg
);
497 mutex_unlock(&ec_dev
->lock
);
501 EXPORT_SYMBOL(cros_ec_cmd_xfer
);
503 int cros_ec_cmd_xfer_status(struct cros_ec_device
*ec_dev
,
504 struct cros_ec_command
*msg
)
508 ret
= cros_ec_cmd_xfer(ec_dev
, msg
);
510 dev_err(ec_dev
->dev
, "Command xfer error (err:%d)\n", ret
);
511 } else if (msg
->result
!= EC_RES_SUCCESS
) {
512 dev_dbg(ec_dev
->dev
, "Command result (err: %d)\n", msg
->result
);
518 EXPORT_SYMBOL(cros_ec_cmd_xfer_status
);
520 static int get_next_event_xfer(struct cros_ec_device
*ec_dev
,
521 struct cros_ec_command
*msg
,
522 int version
, uint32_t size
)
526 msg
->version
= version
;
527 msg
->command
= EC_CMD_GET_NEXT_EVENT
;
531 ret
= cros_ec_cmd_xfer(ec_dev
, msg
);
533 ec_dev
->event_size
= ret
- 1;
534 memcpy(&ec_dev
->event_data
, msg
->data
, ret
);
540 static int get_next_event(struct cros_ec_device
*ec_dev
)
542 u8 buffer
[sizeof(struct cros_ec_command
) + sizeof(ec_dev
->event_data
)];
543 struct cros_ec_command
*msg
= (struct cros_ec_command
*)&buffer
;
544 static int cmd_version
= 1;
547 if (ec_dev
->suspended
) {
548 dev_dbg(ec_dev
->dev
, "Device suspended.\n");
552 if (cmd_version
== 1) {
553 ret
= get_next_event_xfer(ec_dev
, msg
, cmd_version
,
554 sizeof(struct ec_response_get_next_event_v1
));
555 if (ret
< 0 || msg
->result
!= EC_RES_INVALID_VERSION
)
558 /* Fallback to version 0 for future send attempts */
562 ret
= get_next_event_xfer(ec_dev
, msg
, cmd_version
,
563 sizeof(struct ec_response_get_next_event
));
568 static int get_keyboard_state_event(struct cros_ec_device
*ec_dev
)
570 u8 buffer
[sizeof(struct cros_ec_command
) +
571 sizeof(ec_dev
->event_data
.data
)];
572 struct cros_ec_command
*msg
= (struct cros_ec_command
*)&buffer
;
575 msg
->command
= EC_CMD_MKBP_STATE
;
576 msg
->insize
= sizeof(ec_dev
->event_data
.data
);
579 ec_dev
->event_size
= cros_ec_cmd_xfer(ec_dev
, msg
);
580 ec_dev
->event_data
.event_type
= EC_MKBP_EVENT_KEY_MATRIX
;
581 memcpy(&ec_dev
->event_data
.data
, msg
->data
,
582 sizeof(ec_dev
->event_data
.data
));
584 return ec_dev
->event_size
;
587 int cros_ec_get_next_event(struct cros_ec_device
*ec_dev
, bool *wake_event
)
593 if (!ec_dev
->mkbp_event_supported
) {
594 ret
= get_keyboard_state_event(ec_dev
);
604 ret
= get_next_event(ec_dev
);
609 event_type
= ec_dev
->event_data
.event_type
;
610 host_event
= cros_ec_get_host_event(ec_dev
);
613 * Sensor events need to be parsed by the sensor sub-device.
614 * Defer them, and don't report the wakeup here.
616 if (event_type
== EC_MKBP_EVENT_SENSOR_FIFO
)
618 /* Masked host-events should not count as wake events. */
619 else if (host_event
&&
620 !(host_event
& ec_dev
->host_event_wake_mask
))
622 /* Consider all other events as wake events. */
629 EXPORT_SYMBOL(cros_ec_get_next_event
);
631 u32
cros_ec_get_host_event(struct cros_ec_device
*ec_dev
)
635 BUG_ON(!ec_dev
->mkbp_event_supported
);
637 if (ec_dev
->event_data
.event_type
!= EC_MKBP_EVENT_HOST_EVENT
)
640 if (ec_dev
->event_size
!= sizeof(host_event
)) {
641 dev_warn(ec_dev
->dev
, "Invalid host event size\n");
645 host_event
= get_unaligned_le32(&ec_dev
->event_data
.data
.host_event
);
649 EXPORT_SYMBOL(cros_ec_get_host_event
);