Commit d86c21fd authored by Andrew Bresticker's avatar Andrew Bresticker Committed by Lee Jones

mfd: cros_ec: wait for completion of commands that return IN_PROGRESS

When an EC command returns EC_RES_IN_PROGRESS, we need to query
the state of the EC until it indicates that it is no longer busy.
Do this in cros_ec_cmd_xfer() under the EC's mutex so that other
commands (e.g. keyboard, I2C passtru) aren't issued to the EC while
it is working on the in-progress command.

The 10 milliseconds delay and the number of retries are the values
that were used by the flashrom tool when retrying commands.
Signed-off-by: default avatarAndrew Bresticker <abrestic@chromium.org>
Reviewed-by: default avatarSimon Glass <sjg@chromium.org>
Signed-off-by: default avatarJavier Martinez Canillas <javier.martinez@collabora.co.uk>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent 97720706
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/mfd/cros_ec.h> #include <linux/mfd/cros_ec.h>
#include <linux/mfd/cros_ec_commands.h> #include <linux/mfd/cros_ec_commands.h>
#include <linux/delay.h>
#define EC_COMMAND_RETRIES 50
int cros_ec_prepare_tx(struct cros_ec_device *ec_dev, int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
struct cros_ec_command *msg) struct cros_ec_command *msg)
...@@ -69,6 +72,36 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev, ...@@ -69,6 +72,36 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
mutex_lock(&ec_dev->lock); mutex_lock(&ec_dev->lock);
ret = ec_dev->cmd_xfer(ec_dev, msg); ret = ec_dev->cmd_xfer(ec_dev, msg);
if (msg->result == EC_RES_IN_PROGRESS) {
int i;
struct cros_ec_command status_msg;
struct ec_response_get_comms_status status;
status_msg.version = 0;
status_msg.command = EC_CMD_GET_COMMS_STATUS;
status_msg.outdata = NULL;
status_msg.outsize = 0;
status_msg.indata = (uint8_t *)&status;
status_msg.insize = sizeof(status);
/*
* Query the EC's status until it's no longer busy or
* we encounter an error.
*/
for (i = 0; i < EC_COMMAND_RETRIES; i++) {
usleep_range(10000, 11000);
ret = ec_dev->cmd_xfer(ec_dev, &status_msg);
if (ret < 0)
break;
msg->result = status_msg.result;
if (status_msg.result != EC_RES_SUCCESS)
break;
if (!(status.flags & EC_COMMS_STATUS_PROCESSING))
break;
}
}
mutex_unlock(&ec_dev->lock); mutex_unlock(&ec_dev->lock);
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment