GNU Linux-libre 4.19.263-gnu1
[releases.git] / drivers / platform / chrome / cros_ec_proto.c
1 /*
2  * ChromeOS EC communication protocol helper functions
3  *
4  * Copyright (C) 2015 Google, Inc
5  *
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.
9  *
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.
14  *
15  */
16
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>
23
24 #define EC_COMMAND_RETRIES      50
25
26 static int prepare_packet(struct cros_ec_device *ec_dev,
27                           struct cros_ec_command *msg)
28 {
29         struct ec_host_request *request;
30         u8 *out;
31         int i;
32         u8 csum = 0;
33
34         BUG_ON(ec_dev->proto_version != EC_HOST_REQUEST_VERSION);
35         BUG_ON(msg->outsize + sizeof(*request) > ec_dev->dout_size);
36
37         out = ec_dev->dout;
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;
45
46         for (i = 0; i < sizeof(*request); i++)
47                 csum += out[i];
48
49         /* Copy data and update checksum */
50         memcpy(out + sizeof(*request), msg->data, msg->outsize);
51         for (i = 0; i < msg->outsize; i++)
52                 csum += msg->data[i];
53
54         request->checksum = -csum;
55
56         return sizeof(*request) + msg->outsize;
57 }
58
59 static int send_command(struct cros_ec_device *ec_dev,
60                         struct cros_ec_command *msg)
61 {
62         int ret;
63         int (*xfer_fxn)(struct cros_ec_device *ec, struct cros_ec_command *msg);
64
65         if (ec_dev->proto_version > 2)
66                 xfer_fxn = ec_dev->pkt_xfer;
67         else
68                 xfer_fxn = ec_dev->cmd_xfer;
69
70         if (!xfer_fxn) {
71                 /*
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.
75                  */
76                 dev_err_once(ec_dev->dev,
77                              "missing EC transfer API, cannot send command\n");
78                 return -EIO;
79         }
80
81         ret = (*xfer_fxn)(ec_dev, msg);
82         if (msg->result == EC_RES_IN_PROGRESS) {
83                 int i;
84                 struct cros_ec_command *status_msg;
85                 struct ec_response_get_comms_status *status;
86
87                 status_msg = kmalloc(sizeof(*status_msg) + sizeof(*status),
88                                      GFP_KERNEL);
89                 if (!status_msg)
90                         return -ENOMEM;
91
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;
96
97                 /*
98                  * Query the EC's status until it's no longer busy or
99                  * we encounter an error.
100                  */
101                 for (i = 0; i < EC_COMMAND_RETRIES; i++) {
102                         usleep_range(10000, 11000);
103
104                         ret = (*xfer_fxn)(ec_dev, status_msg);
105                         if (ret == -EAGAIN)
106                                 continue;
107                         if (ret < 0)
108                                 break;
109
110                         msg->result = status_msg->result;
111                         if (status_msg->result != EC_RES_SUCCESS)
112                                 break;
113
114                         status = (struct ec_response_get_comms_status *)
115                                  status_msg->data;
116                         if (!(status->flags & EC_COMMS_STATUS_PROCESSING))
117                                 break;
118                 }
119
120                 kfree(status_msg);
121         }
122
123         return ret;
124 }
125
126 int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
127                        struct cros_ec_command *msg)
128 {
129         u8 *out;
130         u8 csum;
131         int i;
132
133         if (ec_dev->proto_version > 2)
134                 return prepare_packet(ec_dev, msg);
135
136         BUG_ON(msg->outsize > EC_PROTO2_MAX_PARAM_SIZE);
137         out = ec_dev->dout;
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;
145
146         return EC_MSG_TX_PROTO_BYTES + msg->outsize;
147 }
148 EXPORT_SYMBOL(cros_ec_prepare_tx);
149
150 int cros_ec_check_result(struct cros_ec_device *ec_dev,
151                          struct cros_ec_command *msg)
152 {
153         switch (msg->result) {
154         case EC_RES_SUCCESS:
155                 return 0;
156         case EC_RES_IN_PROGRESS:
157                 dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
158                         msg->command);
159                 return -EAGAIN;
160         default:
161                 dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n",
162                         msg->command, msg->result);
163                 return 0;
164         }
165 }
166 EXPORT_SYMBOL(cros_ec_check_result);
167
168 /*
169  * cros_ec_get_host_event_wake_mask
170  *
171  * Get the mask of host events that cause wake from suspend.
172  *
173  * @ec_dev: EC device to call
174  * @msg: message structure to use
175  * @mask: result when function returns >=0.
176  *
177  * LOCKING:
178  * the caller has ec_dev->lock mutex, or the caller knows there is
179  * no other command in progress.
180  */
181 static int cros_ec_get_host_event_wake_mask(struct cros_ec_device *ec_dev,
182                                             struct cros_ec_command *msg,
183                                             uint32_t *mask)
184 {
185         struct ec_response_host_event_mask *r;
186         int ret;
187
188         msg->command = EC_CMD_HOST_EVENT_GET_WAKE_MASK;
189         msg->version = 0;
190         msg->outsize = 0;
191         msg->insize = sizeof(*r);
192
193         ret = send_command(ec_dev, msg);
194         if (ret > 0) {
195                 r = (struct ec_response_host_event_mask *)msg->data;
196                 *mask = r->mask;
197         }
198
199         return ret;
200 }
201
202 static int cros_ec_host_command_proto_query(struct cros_ec_device *ec_dev,
203                                             int devidx,
204                                             struct cros_ec_command *msg)
205 {
206         /*
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.
211          */
212         int ret;
213
214         if (!ec_dev->pkt_xfer)
215                 return -EPROTONOSUPPORT;
216
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);
220
221         ret = send_command(ec_dev, msg);
222         /*
223          * Send command once again when timeout occurred.
224          * Fingerprint MCU (FPMCU) is restarted during system boot which
225          * introduces small window in which FPMCU won't respond for any
226          * messages sent by kernel. There is no need to wait before next
227          * attempt because we waited at least EC_MSG_DEADLINE_MS.
228          */
229         if (ret == -ETIMEDOUT)
230                 ret = send_command(ec_dev, msg);
231
232         if (ret < 0) {
233                 dev_dbg(ec_dev->dev,
234                         "failed to check for EC[%d] protocol version: %d\n",
235                         devidx, ret);
236                 return ret;
237         }
238
239         if (devidx > 0 && msg->result == EC_RES_INVALID_COMMAND)
240                 return -ENODEV;
241         else if (msg->result != EC_RES_SUCCESS)
242                 return msg->result;
243
244         return 0;
245 }
246
247 static int cros_ec_host_command_proto_query_v2(struct cros_ec_device *ec_dev)
248 {
249         struct cros_ec_command *msg;
250         struct ec_params_hello *hello_params;
251         struct ec_response_hello *hello_response;
252         int ret;
253         int len = max(sizeof(*hello_params), sizeof(*hello_response));
254
255         msg = kmalloc(sizeof(*msg) + len, GFP_KERNEL);
256         if (!msg)
257                 return -ENOMEM;
258
259         msg->version = 0;
260         msg->command = EC_CMD_HELLO;
261         hello_params = (struct ec_params_hello *)msg->data;
262         msg->outsize = sizeof(*hello_params);
263         hello_response = (struct ec_response_hello *)msg->data;
264         msg->insize = sizeof(*hello_response);
265
266         hello_params->in_data = 0xa0b0c0d0;
267
268         ret = send_command(ec_dev, msg);
269
270         if (ret < 0) {
271                 dev_dbg(ec_dev->dev,
272                         "EC failed to respond to v2 hello: %d\n",
273                         ret);
274                 goto exit;
275         } else if (msg->result != EC_RES_SUCCESS) {
276                 dev_err(ec_dev->dev,
277                         "EC responded to v2 hello with error: %d\n",
278                         msg->result);
279                 ret = msg->result;
280                 goto exit;
281         } else if (hello_response->out_data != 0xa1b2c3d4) {
282                 dev_err(ec_dev->dev,
283                         "EC responded to v2 hello with bad result: %u\n",
284                         hello_response->out_data);
285                 ret = -EBADMSG;
286                 goto exit;
287         }
288
289         ret = 0;
290
291  exit:
292         kfree(msg);
293         return ret;
294 }
295
296 /*
297  * cros_ec_get_host_command_version_mask
298  *
299  * Get the version mask of a given command.
300  *
301  * @ec_dev: EC device to call
302  * @msg: message structure to use
303  * @cmd: command to get the version of.
304  * @mask: result when function returns 0.
305  *
306  * @return 0 on success, error code otherwise
307  *
308  * LOCKING:
309  * the caller has ec_dev->lock mutex or the caller knows there is
310  * no other command in progress.
311  */
312 static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev,
313         u16 cmd, u32 *mask)
314 {
315         struct ec_params_get_cmd_versions *pver;
316         struct ec_response_get_cmd_versions *rver;
317         struct cros_ec_command *msg;
318         int ret;
319
320         msg = kmalloc(sizeof(*msg) + max(sizeof(*rver), sizeof(*pver)),
321                       GFP_KERNEL);
322         if (!msg)
323                 return -ENOMEM;
324
325         msg->version = 0;
326         msg->command = EC_CMD_GET_CMD_VERSIONS;
327         msg->insize = sizeof(*rver);
328         msg->outsize = sizeof(*pver);
329
330         pver = (struct ec_params_get_cmd_versions *)msg->data;
331         pver->cmd = cmd;
332
333         ret = send_command(ec_dev, msg);
334         if (ret > 0) {
335                 rver = (struct ec_response_get_cmd_versions *)msg->data;
336                 *mask = rver->version_mask;
337         }
338
339         kfree(msg);
340
341         return ret;
342 }
343
344 int cros_ec_query_all(struct cros_ec_device *ec_dev)
345 {
346         struct device *dev = ec_dev->dev;
347         struct cros_ec_command *proto_msg;
348         struct ec_response_get_protocol_info *proto_info;
349         u32 ver_mask = 0;
350         int ret;
351
352         proto_msg = kzalloc(sizeof(*proto_msg) + sizeof(*proto_info),
353                             GFP_KERNEL);
354         if (!proto_msg)
355                 return -ENOMEM;
356
357         /* First try sending with proto v3. */
358         ec_dev->proto_version = 3;
359         ret = cros_ec_host_command_proto_query(ec_dev, 0, proto_msg);
360
361         if (ret == 0) {
362                 proto_info = (struct ec_response_get_protocol_info *)
363                         proto_msg->data;
364                 ec_dev->max_request = proto_info->max_request_packet_size -
365                         sizeof(struct ec_host_request);
366                 ec_dev->max_response = proto_info->max_response_packet_size -
367                         sizeof(struct ec_host_response);
368                 ec_dev->proto_version =
369                         min(EC_HOST_REQUEST_VERSION,
370                                         fls(proto_info->protocol_versions) - 1);
371                 dev_dbg(ec_dev->dev,
372                         "using proto v%u\n",
373                         ec_dev->proto_version);
374
375                 ec_dev->din_size = ec_dev->max_response +
376                         sizeof(struct ec_host_response) +
377                         EC_MAX_RESPONSE_OVERHEAD;
378                 ec_dev->dout_size = ec_dev->max_request +
379                         sizeof(struct ec_host_request) +
380                         EC_MAX_REQUEST_OVERHEAD;
381
382                 /*
383                  * Check for PD
384                  */
385                 ret = cros_ec_host_command_proto_query(ec_dev, 1, proto_msg);
386
387                 if (ret) {
388                         dev_dbg(ec_dev->dev, "no PD chip found: %d\n", ret);
389                         ec_dev->max_passthru = 0;
390                 } else {
391                         dev_dbg(ec_dev->dev, "found PD chip\n");
392                         ec_dev->max_passthru =
393                                 proto_info->max_request_packet_size -
394                                 sizeof(struct ec_host_request);
395                 }
396         } else {
397                 /* Try querying with a v2 hello message. */
398                 ec_dev->proto_version = 2;
399                 ret = cros_ec_host_command_proto_query_v2(ec_dev);
400
401                 if (ret == 0) {
402                         /* V2 hello succeeded. */
403                         dev_dbg(ec_dev->dev, "falling back to proto v2\n");
404
405                         ec_dev->max_request = EC_PROTO2_MAX_PARAM_SIZE;
406                         ec_dev->max_response = EC_PROTO2_MAX_PARAM_SIZE;
407                         ec_dev->max_passthru = 0;
408                         ec_dev->pkt_xfer = NULL;
409                         ec_dev->din_size = EC_PROTO2_MSG_BYTES;
410                         ec_dev->dout_size = EC_PROTO2_MSG_BYTES;
411                 } else {
412                         /*
413                          * It's possible for a test to occur too early when
414                          * the EC isn't listening. If this happens, we'll
415                          * test later when the first command is run.
416                          */
417                         ec_dev->proto_version = EC_PROTO_VERSION_UNKNOWN;
418                         dev_dbg(ec_dev->dev, "EC query failed: %d\n", ret);
419                         goto exit;
420                 }
421         }
422
423         devm_kfree(dev, ec_dev->din);
424         devm_kfree(dev, ec_dev->dout);
425
426         ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
427         if (!ec_dev->din) {
428                 ret = -ENOMEM;
429                 goto exit;
430         }
431
432         ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL);
433         if (!ec_dev->dout) {
434                 devm_kfree(dev, ec_dev->din);
435                 ret = -ENOMEM;
436                 goto exit;
437         }
438
439         /* Probe if MKBP event is supported */
440         ret = cros_ec_get_host_command_version_mask(ec_dev,
441                                                     EC_CMD_GET_NEXT_EVENT,
442                                                     &ver_mask);
443         if (ret < 0 || ver_mask == 0)
444                 ec_dev->mkbp_event_supported = 0;
445         else
446                 ec_dev->mkbp_event_supported = 1;
447
448         /*
449          * Get host event wake mask, assume all events are wake events
450          * if unavailable.
451          */
452         ret = cros_ec_get_host_event_wake_mask(ec_dev, proto_msg,
453                                                &ec_dev->host_event_wake_mask);
454         if (ret < 0)
455                 ec_dev->host_event_wake_mask = U32_MAX;
456
457         ret = 0;
458
459 exit:
460         kfree(proto_msg);
461         return ret;
462 }
463 EXPORT_SYMBOL(cros_ec_query_all);
464
465 int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
466                      struct cros_ec_command *msg)
467 {
468         int ret;
469
470         mutex_lock(&ec_dev->lock);
471         if (ec_dev->proto_version == EC_PROTO_VERSION_UNKNOWN) {
472                 ret = cros_ec_query_all(ec_dev);
473                 if (ret) {
474                         dev_err(ec_dev->dev,
475                                 "EC version unknown and query failed; aborting command\n");
476                         mutex_unlock(&ec_dev->lock);
477                         return ret;
478                 }
479         }
480
481         if (msg->insize > ec_dev->max_response) {
482                 dev_dbg(ec_dev->dev, "clamping message receive buffer\n");
483                 msg->insize = ec_dev->max_response;
484         }
485
486         if (msg->command < EC_CMD_PASSTHRU_OFFSET(1)) {
487                 if (msg->outsize > ec_dev->max_request) {
488                         dev_err(ec_dev->dev,
489                                 "request of size %u is too big (max: %u)\n",
490                                 msg->outsize,
491                                 ec_dev->max_request);
492                         mutex_unlock(&ec_dev->lock);
493                         return -EMSGSIZE;
494                 }
495         } else {
496                 if (msg->outsize > ec_dev->max_passthru) {
497                         dev_err(ec_dev->dev,
498                                 "passthru rq of size %u is too big (max: %u)\n",
499                                 msg->outsize,
500                                 ec_dev->max_passthru);
501                         mutex_unlock(&ec_dev->lock);
502                         return -EMSGSIZE;
503                 }
504         }
505         ret = send_command(ec_dev, msg);
506         mutex_unlock(&ec_dev->lock);
507
508         return ret;
509 }
510 EXPORT_SYMBOL(cros_ec_cmd_xfer);
511
512 int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
513                             struct cros_ec_command *msg)
514 {
515         int ret;
516
517         ret = cros_ec_cmd_xfer(ec_dev, msg);
518         if (ret < 0) {
519                 dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
520         } else if (msg->result != EC_RES_SUCCESS) {
521                 dev_dbg(ec_dev->dev, "Command result (err: %d)\n", msg->result);
522                 return -EPROTO;
523         }
524
525         return ret;
526 }
527 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
528
529 static int get_next_event_xfer(struct cros_ec_device *ec_dev,
530                                struct cros_ec_command *msg,
531                                int version, uint32_t size)
532 {
533         int ret;
534
535         msg->version = version;
536         msg->command = EC_CMD_GET_NEXT_EVENT;
537         msg->insize = size;
538         msg->outsize = 0;
539
540         ret = cros_ec_cmd_xfer(ec_dev, msg);
541         if (ret > 0) {
542                 ec_dev->event_size = ret - 1;
543                 memcpy(&ec_dev->event_data, msg->data, ret);
544         }
545
546         return ret;
547 }
548
549 static int get_next_event(struct cros_ec_device *ec_dev)
550 {
551         u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
552         struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
553         static int cmd_version = 1;
554         int ret;
555
556         if (ec_dev->suspended) {
557                 dev_dbg(ec_dev->dev, "Device suspended.\n");
558                 return -EHOSTDOWN;
559         }
560
561         if (cmd_version == 1) {
562                 ret = get_next_event_xfer(ec_dev, msg, cmd_version,
563                                 sizeof(struct ec_response_get_next_event_v1));
564                 if (ret < 0 || msg->result != EC_RES_INVALID_VERSION)
565                         return ret;
566
567                 /* Fallback to version 0 for future send attempts */
568                 cmd_version = 0;
569         }
570
571         ret = get_next_event_xfer(ec_dev, msg, cmd_version,
572                                   sizeof(struct ec_response_get_next_event));
573
574         return ret;
575 }
576
577 static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
578 {
579         u8 buffer[sizeof(struct cros_ec_command) +
580                   sizeof(ec_dev->event_data.data)];
581         struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
582
583         msg->version = 0;
584         msg->command = EC_CMD_MKBP_STATE;
585         msg->insize = sizeof(ec_dev->event_data.data);
586         msg->outsize = 0;
587
588         ec_dev->event_size = cros_ec_cmd_xfer(ec_dev, msg);
589         ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX;
590         memcpy(&ec_dev->event_data.data, msg->data,
591                sizeof(ec_dev->event_data.data));
592
593         return ec_dev->event_size;
594 }
595
596 int cros_ec_get_next_event(struct cros_ec_device *ec_dev, bool *wake_event)
597 {
598         u8 event_type;
599         u32 host_event;
600         int ret;
601
602         if (!ec_dev->mkbp_event_supported) {
603                 ret = get_keyboard_state_event(ec_dev);
604                 if (ret < 0)
605                         return ret;
606
607                 if (wake_event)
608                         *wake_event = true;
609
610                 return ret;
611         }
612
613         ret = get_next_event(ec_dev);
614         if (ret < 0)
615                 return ret;
616
617         if (wake_event) {
618                 event_type = ec_dev->event_data.event_type;
619                 host_event = cros_ec_get_host_event(ec_dev);
620
621                 /*
622                  * Sensor events need to be parsed by the sensor sub-device.
623                  * Defer them, and don't report the wakeup here.
624                  */
625                 if (event_type == EC_MKBP_EVENT_SENSOR_FIFO)
626                         *wake_event = false;
627                 /* Masked host-events should not count as wake events. */
628                 else if (host_event &&
629                          !(host_event & ec_dev->host_event_wake_mask))
630                         *wake_event = false;
631                 /* Consider all other events as wake events. */
632                 else
633                         *wake_event = true;
634         }
635
636         return ret;
637 }
638 EXPORT_SYMBOL(cros_ec_get_next_event);
639
640 u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
641 {
642         u32 host_event;
643
644         BUG_ON(!ec_dev->mkbp_event_supported);
645
646         if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
647                 return 0;
648
649         if (ec_dev->event_size != sizeof(host_event)) {
650                 dev_warn(ec_dev->dev, "Invalid host event size\n");
651                 return 0;
652         }
653
654         host_event = get_unaligned_le32(&ec_dev->event_data.data.host_event);
655
656         return host_event;
657 }
658 EXPORT_SYMBOL(cros_ec_get_host_event);