Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 // ChromeOS EC communication protocol helper functions
0003 //
0004 // Copyright (C) 2015 Google, Inc
0005 
0006 #include <linux/delay.h>
0007 #include <linux/device.h>
0008 #include <linux/module.h>
0009 #include <linux/platform_data/cros_ec_commands.h>
0010 #include <linux/platform_data/cros_ec_proto.h>
0011 #include <linux/slab.h>
0012 #include <asm/unaligned.h>
0013 
0014 #include "cros_ec_trace.h"
0015 
0016 #define EC_COMMAND_RETRIES  50
0017 
0018 static const int cros_ec_error_map[] = {
0019     [EC_RES_INVALID_COMMAND] = -EOPNOTSUPP,
0020     [EC_RES_ERROR] = -EIO,
0021     [EC_RES_INVALID_PARAM] = -EINVAL,
0022     [EC_RES_ACCESS_DENIED] = -EACCES,
0023     [EC_RES_INVALID_RESPONSE] = -EPROTO,
0024     [EC_RES_INVALID_VERSION] = -ENOPROTOOPT,
0025     [EC_RES_INVALID_CHECKSUM] = -EBADMSG,
0026     [EC_RES_IN_PROGRESS] = -EINPROGRESS,
0027     [EC_RES_UNAVAILABLE] = -ENODATA,
0028     [EC_RES_TIMEOUT] = -ETIMEDOUT,
0029     [EC_RES_OVERFLOW] = -EOVERFLOW,
0030     [EC_RES_INVALID_HEADER] = -EBADR,
0031     [EC_RES_REQUEST_TRUNCATED] = -EBADR,
0032     [EC_RES_RESPONSE_TOO_BIG] = -EFBIG,
0033     [EC_RES_BUS_ERROR] = -EFAULT,
0034     [EC_RES_BUSY] = -EBUSY,
0035     [EC_RES_INVALID_HEADER_VERSION] = -EBADMSG,
0036     [EC_RES_INVALID_HEADER_CRC] = -EBADMSG,
0037     [EC_RES_INVALID_DATA_CRC] = -EBADMSG,
0038     [EC_RES_DUP_UNAVAILABLE] = -ENODATA,
0039 };
0040 
0041 static int cros_ec_map_error(uint32_t result)
0042 {
0043     int ret = 0;
0044 
0045     if (result != EC_RES_SUCCESS) {
0046         if (result < ARRAY_SIZE(cros_ec_error_map) && cros_ec_error_map[result])
0047             ret = cros_ec_error_map[result];
0048         else
0049             ret = -EPROTO;
0050     }
0051 
0052     return ret;
0053 }
0054 
0055 static int prepare_tx(struct cros_ec_device *ec_dev,
0056               struct cros_ec_command *msg)
0057 {
0058     struct ec_host_request *request;
0059     u8 *out;
0060     int i;
0061     u8 csum = 0;
0062 
0063     if (msg->outsize + sizeof(*request) > ec_dev->dout_size)
0064         return -EINVAL;
0065 
0066     out = ec_dev->dout;
0067     request = (struct ec_host_request *)out;
0068     request->struct_version = EC_HOST_REQUEST_VERSION;
0069     request->checksum = 0;
0070     request->command = msg->command;
0071     request->command_version = msg->version;
0072     request->reserved = 0;
0073     request->data_len = msg->outsize;
0074 
0075     for (i = 0; i < sizeof(*request); i++)
0076         csum += out[i];
0077 
0078     /* Copy data and update checksum */
0079     memcpy(out + sizeof(*request), msg->data, msg->outsize);
0080     for (i = 0; i < msg->outsize; i++)
0081         csum += msg->data[i];
0082 
0083     request->checksum = -csum;
0084 
0085     return sizeof(*request) + msg->outsize;
0086 }
0087 
0088 static int prepare_tx_legacy(struct cros_ec_device *ec_dev,
0089                  struct cros_ec_command *msg)
0090 {
0091     u8 *out;
0092     u8 csum;
0093     int i;
0094 
0095     if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE)
0096         return -EINVAL;
0097 
0098     out = ec_dev->dout;
0099     out[0] = EC_CMD_VERSION0 + msg->version;
0100     out[1] = msg->command;
0101     out[2] = msg->outsize;
0102     csum = out[0] + out[1] + out[2];
0103     for (i = 0; i < msg->outsize; i++)
0104         csum += out[EC_MSG_TX_HEADER_BYTES + i] = msg->data[i];
0105     out[EC_MSG_TX_HEADER_BYTES + msg->outsize] = csum;
0106 
0107     return EC_MSG_TX_PROTO_BYTES + msg->outsize;
0108 }
0109 
0110 static int cros_ec_xfer_command(struct cros_ec_device *ec_dev, struct cros_ec_command *msg)
0111 {
0112     int ret;
0113     int (*xfer_fxn)(struct cros_ec_device *ec, struct cros_ec_command *msg);
0114 
0115     if (ec_dev->proto_version > 2)
0116         xfer_fxn = ec_dev->pkt_xfer;
0117     else
0118         xfer_fxn = ec_dev->cmd_xfer;
0119 
0120     if (!xfer_fxn) {
0121         /*
0122          * This error can happen if a communication error happened and
0123          * the EC is trying to use protocol v2, on an underlying
0124          * communication mechanism that does not support v2.
0125          */
0126         dev_err_once(ec_dev->dev, "missing EC transfer API, cannot send command\n");
0127         return -EIO;
0128     }
0129 
0130     trace_cros_ec_request_start(msg);
0131     ret = (*xfer_fxn)(ec_dev, msg);
0132     trace_cros_ec_request_done(msg, ret);
0133 
0134     return ret;
0135 }
0136 
0137 static int cros_ec_wait_until_complete(struct cros_ec_device *ec_dev, uint32_t *result)
0138 {
0139     struct {
0140         struct cros_ec_command msg;
0141         struct ec_response_get_comms_status status;
0142     } __packed buf;
0143     struct cros_ec_command *msg = &buf.msg;
0144     struct ec_response_get_comms_status *status = &buf.status;
0145     int ret = 0, i;
0146 
0147     msg->version = 0;
0148     msg->command = EC_CMD_GET_COMMS_STATUS;
0149     msg->insize = sizeof(*status);
0150     msg->outsize = 0;
0151 
0152     /* Query the EC's status until it's no longer busy or we encounter an error. */
0153     for (i = 0; i < EC_COMMAND_RETRIES; ++i) {
0154         usleep_range(10000, 11000);
0155 
0156         ret = cros_ec_xfer_command(ec_dev, msg);
0157         if (ret == -EAGAIN)
0158             continue;
0159         if (ret < 0)
0160             return ret;
0161 
0162         *result = msg->result;
0163         if (msg->result != EC_RES_SUCCESS)
0164             return ret;
0165 
0166         if (ret == 0) {
0167             ret = -EPROTO;
0168             break;
0169         }
0170 
0171         if (!(status->flags & EC_COMMS_STATUS_PROCESSING))
0172             return ret;
0173     }
0174 
0175     if (i >= EC_COMMAND_RETRIES)
0176         ret = -EAGAIN;
0177 
0178     return ret;
0179 }
0180 
0181 static int cros_ec_send_command(struct cros_ec_device *ec_dev, struct cros_ec_command *msg)
0182 {
0183     int ret = cros_ec_xfer_command(ec_dev, msg);
0184 
0185     if (msg->result == EC_RES_IN_PROGRESS)
0186         ret = cros_ec_wait_until_complete(ec_dev, &msg->result);
0187 
0188     return ret;
0189 }
0190 
0191 /**
0192  * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
0193  * @ec_dev: Device to register.
0194  * @msg: Message to write.
0195  *
0196  * This is used by all ChromeOS EC drivers to prepare the outgoing message
0197  * according to different protocol versions.
0198  *
0199  * Return: number of prepared bytes on success or negative error code.
0200  */
0201 int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
0202                struct cros_ec_command *msg)
0203 {
0204     if (ec_dev->proto_version > 2)
0205         return prepare_tx(ec_dev, msg);
0206 
0207     return prepare_tx_legacy(ec_dev, msg);
0208 }
0209 EXPORT_SYMBOL(cros_ec_prepare_tx);
0210 
0211 /**
0212  * cros_ec_check_result() - Check ec_msg->result.
0213  * @ec_dev: EC device.
0214  * @msg: Message to check.
0215  *
0216  * This is used by ChromeOS EC drivers to check the ec_msg->result for
0217  * EC_RES_IN_PROGRESS and to warn about them.
0218  *
0219  * The function should not check for furthermore error codes.  Otherwise,
0220  * it would break the ABI.
0221  *
0222  * Return: -EAGAIN if ec_msg->result == EC_RES_IN_PROGRESS.  Otherwise, 0.
0223  */
0224 int cros_ec_check_result(struct cros_ec_device *ec_dev,
0225              struct cros_ec_command *msg)
0226 {
0227     switch (msg->result) {
0228     case EC_RES_SUCCESS:
0229         return 0;
0230     case EC_RES_IN_PROGRESS:
0231         dev_dbg(ec_dev->dev, "command 0x%02x in progress\n",
0232             msg->command);
0233         return -EAGAIN;
0234     default:
0235         dev_dbg(ec_dev->dev, "command 0x%02x returned %d\n",
0236             msg->command, msg->result);
0237         return 0;
0238     }
0239 }
0240 EXPORT_SYMBOL(cros_ec_check_result);
0241 
0242 /*
0243  * cros_ec_get_host_event_wake_mask
0244  *
0245  * Get the mask of host events that cause wake from suspend.
0246  *
0247  * @ec_dev: EC device to call
0248  * @msg: message structure to use
0249  * @mask: result when function returns 0.
0250  *
0251  * LOCKING:
0252  * the caller has ec_dev->lock mutex, or the caller knows there is
0253  * no other command in progress.
0254  */
0255 static int cros_ec_get_host_event_wake_mask(struct cros_ec_device *ec_dev, uint32_t *mask)
0256 {
0257     struct cros_ec_command *msg;
0258     struct ec_response_host_event_mask *r;
0259     int ret, mapped;
0260 
0261     msg = kzalloc(sizeof(*msg) + sizeof(*r), GFP_KERNEL);
0262     if (!msg)
0263         return -ENOMEM;
0264 
0265     msg->command = EC_CMD_HOST_EVENT_GET_WAKE_MASK;
0266     msg->insize = sizeof(*r);
0267 
0268     ret = cros_ec_send_command(ec_dev, msg);
0269     if (ret < 0)
0270         goto exit;
0271 
0272     mapped = cros_ec_map_error(msg->result);
0273     if (mapped) {
0274         ret = mapped;
0275         goto exit;
0276     }
0277 
0278     if (ret == 0) {
0279         ret = -EPROTO;
0280         goto exit;
0281     }
0282 
0283     r = (struct ec_response_host_event_mask *)msg->data;
0284     *mask = r->mask;
0285     ret = 0;
0286 exit:
0287     kfree(msg);
0288     return ret;
0289 }
0290 
0291 static int cros_ec_get_proto_info(struct cros_ec_device *ec_dev, int devidx)
0292 {
0293     struct cros_ec_command *msg;
0294     struct ec_response_get_protocol_info *info;
0295     int ret, mapped;
0296 
0297     ec_dev->proto_version = 3;
0298     if (devidx > 0)
0299         ec_dev->max_passthru = 0;
0300 
0301     msg = kzalloc(sizeof(*msg) + sizeof(*info), GFP_KERNEL);
0302     if (!msg)
0303         return -ENOMEM;
0304 
0305     msg->command = EC_CMD_PASSTHRU_OFFSET(devidx) | EC_CMD_GET_PROTOCOL_INFO;
0306     msg->insize = sizeof(*info);
0307 
0308     ret = cros_ec_send_command(ec_dev, msg);
0309     /*
0310      * Send command once again when timeout occurred.
0311      * Fingerprint MCU (FPMCU) is restarted during system boot which
0312      * introduces small window in which FPMCU won't respond for any
0313      * messages sent by kernel. There is no need to wait before next
0314      * attempt because we waited at least EC_MSG_DEADLINE_MS.
0315      */
0316     if (ret == -ETIMEDOUT)
0317         ret = cros_ec_send_command(ec_dev, msg);
0318 
0319     if (ret < 0) {
0320         dev_dbg(ec_dev->dev,
0321             "failed to check for EC[%d] protocol version: %d\n",
0322             devidx, ret);
0323         goto exit;
0324     }
0325 
0326     mapped = cros_ec_map_error(msg->result);
0327     if (mapped) {
0328         ret = mapped;
0329         goto exit;
0330     }
0331 
0332     if (ret == 0) {
0333         ret = -EPROTO;
0334         goto exit;
0335     }
0336 
0337     info = (struct ec_response_get_protocol_info *)msg->data;
0338 
0339     switch (devidx) {
0340     case CROS_EC_DEV_EC_INDEX:
0341         ec_dev->max_request = info->max_request_packet_size -
0342                         sizeof(struct ec_host_request);
0343         ec_dev->max_response = info->max_response_packet_size -
0344                         sizeof(struct ec_host_response);
0345         ec_dev->proto_version = min(EC_HOST_REQUEST_VERSION,
0346                         fls(info->protocol_versions) - 1);
0347         ec_dev->din_size = info->max_response_packet_size + EC_MAX_RESPONSE_OVERHEAD;
0348         ec_dev->dout_size = info->max_request_packet_size + EC_MAX_REQUEST_OVERHEAD;
0349 
0350         dev_dbg(ec_dev->dev, "using proto v%u\n", ec_dev->proto_version);
0351         break;
0352     case CROS_EC_DEV_PD_INDEX:
0353         ec_dev->max_passthru = info->max_request_packet_size -
0354                         sizeof(struct ec_host_request);
0355 
0356         dev_dbg(ec_dev->dev, "found PD chip\n");
0357         break;
0358     default:
0359         dev_dbg(ec_dev->dev, "unknown passthru index: %d\n", devidx);
0360         break;
0361     }
0362 
0363     ret = 0;
0364 exit:
0365     kfree(msg);
0366     return ret;
0367 }
0368 
0369 static int cros_ec_get_proto_info_legacy(struct cros_ec_device *ec_dev)
0370 {
0371     struct cros_ec_command *msg;
0372     struct ec_params_hello *params;
0373     struct ec_response_hello *response;
0374     int ret, mapped;
0375 
0376     ec_dev->proto_version = 2;
0377 
0378     msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*response)), GFP_KERNEL);
0379     if (!msg)
0380         return -ENOMEM;
0381 
0382     msg->command = EC_CMD_HELLO;
0383     msg->insize = sizeof(*response);
0384     msg->outsize = sizeof(*params);
0385 
0386     params = (struct ec_params_hello *)msg->data;
0387     params->in_data = 0xa0b0c0d0;
0388 
0389     ret = cros_ec_send_command(ec_dev, msg);
0390     if (ret < 0) {
0391         dev_dbg(ec_dev->dev, "EC failed to respond to v2 hello: %d\n", ret);
0392         goto exit;
0393     }
0394 
0395     mapped = cros_ec_map_error(msg->result);
0396     if (mapped) {
0397         ret = mapped;
0398         dev_err(ec_dev->dev, "EC responded to v2 hello with error: %d\n", msg->result);
0399         goto exit;
0400     }
0401 
0402     if (ret == 0) {
0403         ret = -EPROTO;
0404         goto exit;
0405     }
0406 
0407     response = (struct ec_response_hello *)msg->data;
0408     if (response->out_data != 0xa1b2c3d4) {
0409         dev_err(ec_dev->dev,
0410             "EC responded to v2 hello with bad result: %u\n",
0411             response->out_data);
0412         ret = -EBADMSG;
0413         goto exit;
0414     }
0415 
0416     ec_dev->max_request = EC_PROTO2_MAX_PARAM_SIZE;
0417     ec_dev->max_response = EC_PROTO2_MAX_PARAM_SIZE;
0418     ec_dev->max_passthru = 0;
0419     ec_dev->pkt_xfer = NULL;
0420     ec_dev->din_size = EC_PROTO2_MSG_BYTES;
0421     ec_dev->dout_size = EC_PROTO2_MSG_BYTES;
0422 
0423     dev_dbg(ec_dev->dev, "falling back to proto v2\n");
0424     ret = 0;
0425 exit:
0426     kfree(msg);
0427     return ret;
0428 }
0429 
0430 /*
0431  * cros_ec_get_host_command_version_mask
0432  *
0433  * Get the version mask of a given command.
0434  *
0435  * @ec_dev: EC device to call
0436  * @msg: message structure to use
0437  * @cmd: command to get the version of.
0438  * @mask: result when function returns 0.
0439  *
0440  * @return 0 on success, error code otherwise
0441  *
0442  * LOCKING:
0443  * the caller has ec_dev->lock mutex or the caller knows there is
0444  * no other command in progress.
0445  */
0446 static int cros_ec_get_host_command_version_mask(struct cros_ec_device *ec_dev, u16 cmd, u32 *mask)
0447 {
0448     struct ec_params_get_cmd_versions *pver;
0449     struct ec_response_get_cmd_versions *rver;
0450     struct cros_ec_command *msg;
0451     int ret, mapped;
0452 
0453     msg = kmalloc(sizeof(*msg) + max(sizeof(*rver), sizeof(*pver)),
0454               GFP_KERNEL);
0455     if (!msg)
0456         return -ENOMEM;
0457 
0458     msg->version = 0;
0459     msg->command = EC_CMD_GET_CMD_VERSIONS;
0460     msg->insize = sizeof(*rver);
0461     msg->outsize = sizeof(*pver);
0462 
0463     pver = (struct ec_params_get_cmd_versions *)msg->data;
0464     pver->cmd = cmd;
0465 
0466     ret = cros_ec_send_command(ec_dev, msg);
0467     if (ret < 0)
0468         goto exit;
0469 
0470     mapped = cros_ec_map_error(msg->result);
0471     if (mapped) {
0472         ret = mapped;
0473         goto exit;
0474     }
0475 
0476     if (ret == 0) {
0477         ret = -EPROTO;
0478         goto exit;
0479     }
0480 
0481     rver = (struct ec_response_get_cmd_versions *)msg->data;
0482     *mask = rver->version_mask;
0483     ret = 0;
0484 exit:
0485     kfree(msg);
0486     return ret;
0487 }
0488 
0489 /**
0490  * cros_ec_query_all() -  Query the protocol version supported by the
0491  *         ChromeOS EC.
0492  * @ec_dev: Device to register.
0493  *
0494  * Return: 0 on success or negative error code.
0495  */
0496 int cros_ec_query_all(struct cros_ec_device *ec_dev)
0497 {
0498     struct device *dev = ec_dev->dev;
0499     u32 ver_mask;
0500     int ret;
0501 
0502     /* First try sending with proto v3. */
0503     if (!cros_ec_get_proto_info(ec_dev, CROS_EC_DEV_EC_INDEX)) {
0504         /* Check for PD. */
0505         cros_ec_get_proto_info(ec_dev, CROS_EC_DEV_PD_INDEX);
0506     } else {
0507         /* Try querying with a v2 hello message. */
0508         ret = cros_ec_get_proto_info_legacy(ec_dev);
0509         if (ret) {
0510             /*
0511              * It's possible for a test to occur too early when
0512              * the EC isn't listening. If this happens, we'll
0513              * test later when the first command is run.
0514              */
0515             ec_dev->proto_version = EC_PROTO_VERSION_UNKNOWN;
0516             dev_dbg(ec_dev->dev, "EC query failed: %d\n", ret);
0517             return ret;
0518         }
0519     }
0520 
0521     devm_kfree(dev, ec_dev->din);
0522     devm_kfree(dev, ec_dev->dout);
0523 
0524     ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
0525     if (!ec_dev->din) {
0526         ret = -ENOMEM;
0527         goto exit;
0528     }
0529 
0530     ec_dev->dout = devm_kzalloc(dev, ec_dev->dout_size, GFP_KERNEL);
0531     if (!ec_dev->dout) {
0532         devm_kfree(dev, ec_dev->din);
0533         ret = -ENOMEM;
0534         goto exit;
0535     }
0536 
0537     /* Probe if MKBP event is supported */
0538     ret = cros_ec_get_host_command_version_mask(ec_dev, EC_CMD_GET_NEXT_EVENT, &ver_mask);
0539     if (ret < 0 || ver_mask == 0) {
0540         ec_dev->mkbp_event_supported = 0;
0541     } else {
0542         ec_dev->mkbp_event_supported = fls(ver_mask);
0543 
0544         dev_dbg(ec_dev->dev, "MKBP support version %u\n", ec_dev->mkbp_event_supported - 1);
0545     }
0546 
0547     /* Probe if host sleep v1 is supported for S0ix failure detection. */
0548     ret = cros_ec_get_host_command_version_mask(ec_dev, EC_CMD_HOST_SLEEP_EVENT, &ver_mask);
0549     ec_dev->host_sleep_v1 = (ret == 0 && (ver_mask & EC_VER_MASK(1)));
0550 
0551     /* Get host event wake mask. */
0552     ret = cros_ec_get_host_event_wake_mask(ec_dev, &ec_dev->host_event_wake_mask);
0553     if (ret < 0) {
0554         /*
0555          * If the EC doesn't support EC_CMD_HOST_EVENT_GET_WAKE_MASK,
0556          * use a reasonable default. Note that we ignore various
0557          * battery, AC status, and power-state events, because (a)
0558          * those can be quite common (e.g., when sitting at full
0559          * charge, on AC) and (b) these are not actionable wake events;
0560          * if anything, we'd like to continue suspending (to save
0561          * power), not wake up.
0562          */
0563         ec_dev->host_event_wake_mask = U32_MAX &
0564             ~(EC_HOST_EVENT_MASK(EC_HOST_EVENT_LID_CLOSED) |
0565               EC_HOST_EVENT_MASK(EC_HOST_EVENT_AC_DISCONNECTED) |
0566               EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_LOW) |
0567               EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_CRITICAL) |
0568               EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY) |
0569               EC_HOST_EVENT_MASK(EC_HOST_EVENT_PD_MCU) |
0570               EC_HOST_EVENT_MASK(EC_HOST_EVENT_BATTERY_STATUS));
0571         /*
0572          * Old ECs may not support this command. Complain about all
0573          * other errors.
0574          */
0575         if (ret != -EOPNOTSUPP)
0576             dev_err(ec_dev->dev,
0577                 "failed to retrieve wake mask: %d\n", ret);
0578     }
0579 
0580     ret = 0;
0581 
0582 exit:
0583     return ret;
0584 }
0585 EXPORT_SYMBOL(cros_ec_query_all);
0586 
0587 /**
0588  * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
0589  * @ec_dev: EC device.
0590  * @msg: Message to write.
0591  *
0592  * Call this to send a command to the ChromeOS EC. This should be used instead
0593  * of calling the EC's cmd_xfer() callback directly. This function does not
0594  * convert EC command execution error codes to Linux error codes. Most
0595  * in-kernel users will want to use cros_ec_cmd_xfer_status() instead since
0596  * that function implements the conversion.
0597  *
0598  * Return:
0599  * >0 - EC command was executed successfully. The return value is the number
0600  *      of bytes returned by the EC (excluding the header).
0601  * =0 - EC communication was successful. EC command execution results are
0602  *      reported in msg->result. The result will be EC_RES_SUCCESS if the
0603  *      command was executed successfully or report an EC command execution
0604  *      error.
0605  * <0 - EC communication error. Return value is the Linux error code.
0606  */
0607 int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, struct cros_ec_command *msg)
0608 {
0609     int ret;
0610 
0611     mutex_lock(&ec_dev->lock);
0612     if (ec_dev->proto_version == EC_PROTO_VERSION_UNKNOWN) {
0613         ret = cros_ec_query_all(ec_dev);
0614         if (ret) {
0615             dev_err(ec_dev->dev,
0616                 "EC version unknown and query failed; aborting command\n");
0617             mutex_unlock(&ec_dev->lock);
0618             return ret;
0619         }
0620     }
0621 
0622     if (msg->insize > ec_dev->max_response) {
0623         dev_dbg(ec_dev->dev, "clamping message receive buffer\n");
0624         msg->insize = ec_dev->max_response;
0625     }
0626 
0627     if (msg->command < EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX)) {
0628         if (msg->outsize > ec_dev->max_request) {
0629             dev_err(ec_dev->dev,
0630                 "request of size %u is too big (max: %u)\n",
0631                 msg->outsize,
0632                 ec_dev->max_request);
0633             mutex_unlock(&ec_dev->lock);
0634             return -EMSGSIZE;
0635         }
0636     } else {
0637         if (msg->outsize > ec_dev->max_passthru) {
0638             dev_err(ec_dev->dev,
0639                 "passthru rq of size %u is too big (max: %u)\n",
0640                 msg->outsize,
0641                 ec_dev->max_passthru);
0642             mutex_unlock(&ec_dev->lock);
0643             return -EMSGSIZE;
0644         }
0645     }
0646 
0647     ret = cros_ec_send_command(ec_dev, msg);
0648     mutex_unlock(&ec_dev->lock);
0649 
0650     return ret;
0651 }
0652 EXPORT_SYMBOL(cros_ec_cmd_xfer);
0653 
0654 /**
0655  * cros_ec_cmd_xfer_status() - Send a command to the ChromeOS EC.
0656  * @ec_dev: EC device.
0657  * @msg: Message to write.
0658  *
0659  * Call this to send a command to the ChromeOS EC. This should be used instead of calling the EC's
0660  * cmd_xfer() callback directly. It returns success status only if both the command was transmitted
0661  * successfully and the EC replied with success status.
0662  *
0663  * Return:
0664  * >=0 - The number of bytes transferred.
0665  * <0 - Linux error code
0666  */
0667 int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
0668                 struct cros_ec_command *msg)
0669 {
0670     int ret, mapped;
0671 
0672     ret = cros_ec_cmd_xfer(ec_dev, msg);
0673     if (ret < 0)
0674         return ret;
0675 
0676     mapped = cros_ec_map_error(msg->result);
0677     if (mapped) {
0678         dev_dbg(ec_dev->dev, "Command result (err: %d [%d])\n",
0679             msg->result, mapped);
0680         ret = mapped;
0681     }
0682 
0683     return ret;
0684 }
0685 EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
0686 
0687 static int get_next_event_xfer(struct cros_ec_device *ec_dev,
0688                    struct cros_ec_command *msg,
0689                    struct ec_response_get_next_event_v1 *event,
0690                    int version, uint32_t size)
0691 {
0692     int ret;
0693 
0694     msg->version = version;
0695     msg->command = EC_CMD_GET_NEXT_EVENT;
0696     msg->insize = size;
0697     msg->outsize = 0;
0698 
0699     ret = cros_ec_cmd_xfer_status(ec_dev, msg);
0700     if (ret > 0) {
0701         ec_dev->event_size = ret - 1;
0702         ec_dev->event_data = *event;
0703     }
0704 
0705     return ret;
0706 }
0707 
0708 static int get_next_event(struct cros_ec_device *ec_dev)
0709 {
0710     struct {
0711         struct cros_ec_command msg;
0712         struct ec_response_get_next_event_v1 event;
0713     } __packed buf;
0714     struct cros_ec_command *msg = &buf.msg;
0715     struct ec_response_get_next_event_v1 *event = &buf.event;
0716     const int cmd_version = ec_dev->mkbp_event_supported - 1;
0717 
0718     memset(msg, 0, sizeof(*msg));
0719     if (ec_dev->suspended) {
0720         dev_dbg(ec_dev->dev, "Device suspended.\n");
0721         return -EHOSTDOWN;
0722     }
0723 
0724     if (cmd_version == 0)
0725         return get_next_event_xfer(ec_dev, msg, event, 0,
0726                   sizeof(struct ec_response_get_next_event));
0727 
0728     return get_next_event_xfer(ec_dev, msg, event, cmd_version,
0729                 sizeof(struct ec_response_get_next_event_v1));
0730 }
0731 
0732 static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
0733 {
0734     u8 buffer[sizeof(struct cros_ec_command) +
0735           sizeof(ec_dev->event_data.data)];
0736     struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
0737 
0738     msg->version = 0;
0739     msg->command = EC_CMD_MKBP_STATE;
0740     msg->insize = sizeof(ec_dev->event_data.data);
0741     msg->outsize = 0;
0742 
0743     ec_dev->event_size = cros_ec_cmd_xfer_status(ec_dev, msg);
0744     ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX;
0745     memcpy(&ec_dev->event_data.data, msg->data,
0746            sizeof(ec_dev->event_data.data));
0747 
0748     return ec_dev->event_size;
0749 }
0750 
0751 /**
0752  * cros_ec_get_next_event() - Fetch next event from the ChromeOS EC.
0753  * @ec_dev: Device to fetch event from.
0754  * @wake_event: Pointer to a bool set to true upon return if the event might be
0755  *              treated as a wake event. Ignored if null.
0756  * @has_more_events: Pointer to bool set to true if more than one event is
0757  *              pending.
0758  *              Some EC will set this flag to indicate cros_ec_get_next_event()
0759  *              can be called multiple times in a row.
0760  *              It is an optimization to prevent issuing a EC command for
0761  *              nothing or wait for another interrupt from the EC to process
0762  *              the next message.
0763  *              Ignored if null.
0764  *
0765  * Return: negative error code on errors; 0 for no data; or else number of
0766  * bytes received (i.e., an event was retrieved successfully). Event types are
0767  * written out to @ec_dev->event_data.event_type on success.
0768  */
0769 int cros_ec_get_next_event(struct cros_ec_device *ec_dev,
0770                bool *wake_event,
0771                bool *has_more_events)
0772 {
0773     u8 event_type;
0774     u32 host_event;
0775     int ret;
0776 
0777     /*
0778      * Default value for wake_event.
0779      * Wake up on keyboard event, wake up for spurious interrupt or link
0780      * error to the EC.
0781      */
0782     if (wake_event)
0783         *wake_event = true;
0784 
0785     /*
0786      * Default value for has_more_events.
0787      * EC will raise another interrupt if AP does not process all events
0788      * anyway.
0789      */
0790     if (has_more_events)
0791         *has_more_events = false;
0792 
0793     if (!ec_dev->mkbp_event_supported)
0794         return get_keyboard_state_event(ec_dev);
0795 
0796     ret = get_next_event(ec_dev);
0797     if (ret <= 0)
0798         return ret;
0799 
0800     if (has_more_events)
0801         *has_more_events = ec_dev->event_data.event_type &
0802             EC_MKBP_HAS_MORE_EVENTS;
0803     ec_dev->event_data.event_type &= EC_MKBP_EVENT_TYPE_MASK;
0804 
0805     if (wake_event) {
0806         event_type = ec_dev->event_data.event_type;
0807         host_event = cros_ec_get_host_event(ec_dev);
0808 
0809         /*
0810          * Sensor events need to be parsed by the sensor sub-device.
0811          * Defer them, and don't report the wakeup here.
0812          */
0813         if (event_type == EC_MKBP_EVENT_SENSOR_FIFO) {
0814             *wake_event = false;
0815         } else if (host_event) {
0816             /* rtc_update_irq() already handles wakeup events. */
0817             if (host_event & EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC))
0818                 *wake_event = false;
0819             /* Masked host-events should not count as wake events. */
0820             if (!(host_event & ec_dev->host_event_wake_mask))
0821                 *wake_event = false;
0822         }
0823     }
0824 
0825     return ret;
0826 }
0827 EXPORT_SYMBOL(cros_ec_get_next_event);
0828 
0829 /**
0830  * cros_ec_get_host_event() - Return a mask of event set by the ChromeOS EC.
0831  * @ec_dev: Device to fetch event from.
0832  *
0833  * When MKBP is supported, when the EC raises an interrupt, we collect the
0834  * events raised and call the functions in the ec notifier. This function
0835  * is a helper to know which events are raised.
0836  *
0837  * Return: 0 on error or non-zero bitmask of one or more EC_HOST_EVENT_*.
0838  */
0839 u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
0840 {
0841     u32 host_event;
0842 
0843     if (!ec_dev->mkbp_event_supported)
0844         return 0;
0845 
0846     if (ec_dev->event_data.event_type != EC_MKBP_EVENT_HOST_EVENT)
0847         return 0;
0848 
0849     if (ec_dev->event_size != sizeof(host_event)) {
0850         dev_warn(ec_dev->dev, "Invalid host event size\n");
0851         return 0;
0852     }
0853 
0854     host_event = get_unaligned_le32(&ec_dev->event_data.data.host_event);
0855 
0856     return host_event;
0857 }
0858 EXPORT_SYMBOL(cros_ec_get_host_event);
0859 
0860 /**
0861  * cros_ec_check_features() - Test for the presence of EC features
0862  *
0863  * @ec: EC device, does not have to be connected directly to the AP,
0864  *      can be daisy chained through another device.
0865  * @feature: One of ec_feature_code bit.
0866  *
0867  * Call this function to test whether the ChromeOS EC supports a feature.
0868  *
0869  * Return: true if supported, false if not (or if an error was encountered).
0870  */
0871 bool cros_ec_check_features(struct cros_ec_dev *ec, int feature)
0872 {
0873     struct ec_response_get_features *features = &ec->features;
0874     int ret;
0875 
0876     if (features->flags[0] == -1U && features->flags[1] == -1U) {
0877         /* features bitmap not read yet */
0878         ret = cros_ec_cmd(ec->ec_dev, 0, EC_CMD_GET_FEATURES + ec->cmd_offset,
0879                   NULL, 0, features, sizeof(*features));
0880         if (ret < 0) {
0881             dev_warn(ec->dev, "cannot get EC features: %d\n", ret);
0882             memset(features, 0, sizeof(*features));
0883         }
0884 
0885         dev_dbg(ec->dev, "EC features %08x %08x\n",
0886             features->flags[0], features->flags[1]);
0887     }
0888 
0889     return !!(features->flags[feature / 32] & EC_FEATURE_MASK_0(feature));
0890 }
0891 EXPORT_SYMBOL_GPL(cros_ec_check_features);
0892 
0893 /**
0894  * cros_ec_get_sensor_count() - Return the number of MEMS sensors supported.
0895  *
0896  * @ec: EC device, does not have to be connected directly to the AP,
0897  *      can be daisy chained through another device.
0898  * Return: < 0 in case of error.
0899  */
0900 int cros_ec_get_sensor_count(struct cros_ec_dev *ec)
0901 {
0902     /*
0903      * Issue a command to get the number of sensor reported.
0904      * If not supported, check for legacy mode.
0905      */
0906     int ret, sensor_count;
0907     struct ec_params_motion_sense *params;
0908     struct ec_response_motion_sense *resp;
0909     struct cros_ec_command *msg;
0910     struct cros_ec_device *ec_dev = ec->ec_dev;
0911     u8 status;
0912 
0913     msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*resp)),
0914               GFP_KERNEL);
0915     if (!msg)
0916         return -ENOMEM;
0917 
0918     msg->version = 1;
0919     msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
0920     msg->outsize = sizeof(*params);
0921     msg->insize = sizeof(*resp);
0922 
0923     params = (struct ec_params_motion_sense *)msg->data;
0924     params->cmd = MOTIONSENSE_CMD_DUMP;
0925 
0926     ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
0927     if (ret < 0) {
0928         sensor_count = ret;
0929     } else {
0930         resp = (struct ec_response_motion_sense *)msg->data;
0931         sensor_count = resp->dump.sensor_count;
0932     }
0933     kfree(msg);
0934 
0935     /*
0936      * Check legacy mode: Let's find out if sensors are accessible
0937      * via LPC interface.
0938      */
0939     if (sensor_count < 0 && ec->cmd_offset == 0 && ec_dev->cmd_readmem) {
0940         ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS,
0941                 1, &status);
0942         if (ret >= 0 &&
0943             (status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) {
0944             /*
0945              * We have 2 sensors, one in the lid, one in the base.
0946              */
0947             sensor_count = 2;
0948         } else {
0949             /*
0950              * EC uses LPC interface and no sensors are presented.
0951              */
0952             sensor_count = 0;
0953         }
0954     }
0955     return sensor_count;
0956 }
0957 EXPORT_SYMBOL_GPL(cros_ec_get_sensor_count);
0958 
0959 /**
0960  * cros_ec_cmd - Send a command to the EC.
0961  *
0962  * @ec_dev: EC device
0963  * @version: EC command version
0964  * @command: EC command
0965  * @outdata: EC command output data
0966  * @outsize: Size of outdata
0967  * @indata: EC command input data
0968  * @insize: Size of indata
0969  *
0970  * Return: >= 0 on success, negative error number on failure.
0971  */
0972 int cros_ec_cmd(struct cros_ec_device *ec_dev,
0973         unsigned int version,
0974         int command,
0975         void *outdata,
0976         size_t outsize,
0977         void *indata,
0978         size_t insize)
0979 {
0980     struct cros_ec_command *msg;
0981     int ret;
0982 
0983     msg = kzalloc(sizeof(*msg) + max(insize, outsize), GFP_KERNEL);
0984     if (!msg)
0985         return -ENOMEM;
0986 
0987     msg->version = version;
0988     msg->command = command;
0989     msg->outsize = outsize;
0990     msg->insize = insize;
0991 
0992     if (outsize)
0993         memcpy(msg->data, outdata, outsize);
0994 
0995     ret = cros_ec_cmd_xfer_status(ec_dev, msg);
0996     if (ret < 0)
0997         goto error;
0998 
0999     if (insize)
1000         memcpy(indata, msg->data, insize);
1001 error:
1002     kfree(msg);
1003     return ret;
1004 }
1005 EXPORT_SYMBOL_GPL(cros_ec_cmd);