root/drivers/platform/chrome/cros_ec_proto.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. prepare_packet
  2. send_command
  3. cros_ec_prepare_tx
  4. cros_ec_check_result
  5. cros_ec_get_host_event_wake_mask
  6. cros_ec_host_command_proto_query
  7. cros_ec_host_command_proto_query_v2
  8. cros_ec_get_host_command_version_mask
  9. cros_ec_query_all
  10. cros_ec_cmd_xfer
  11. cros_ec_cmd_xfer_status
  12. get_next_event_xfer
  13. get_next_event
  14. get_keyboard_state_event
  15. cros_ec_get_next_event
  16. cros_ec_get_host_event

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

/* [<][>][^][v][top][bottom][index][help] */