summaryrefslogtreecommitdiff
path: root/drivers/mfd/cros_ec.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mfd/cros_ec.c')
-rw-r--r--drivers/mfd/cros_ec.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 6acfe036d522..5d5c41ac3845 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* ChromeOS EC multi-function device
*
* Copyright (C) 2012 Google, Inc
*
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
* The ChromeOS EC multi function device is used to mux all the requests
* to the EC device for its multiple features: keyboard controller,
* battery charging and regulator control, firmware update.
@@ -75,20 +67,49 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
{
+ int ret;
struct {
struct cros_ec_command msg;
- struct ec_params_host_sleep_event req;
+ union {
+ struct ec_params_host_sleep_event req0;
+ struct ec_params_host_sleep_event_v1 req1;
+ struct ec_response_host_sleep_event_v1 resp1;
+ } u;
} __packed buf;
memset(&buf, 0, sizeof(buf));
- buf.req.sleep_event = sleep_event;
+ if (ec_dev->host_sleep_v1) {
+ buf.u.req1.sleep_event = sleep_event;
+ buf.u.req1.suspend_params.sleep_timeout_ms =
+ EC_HOST_SLEEP_TIMEOUT_DEFAULT;
+
+ buf.msg.outsize = sizeof(buf.u.req1);
+ if ((sleep_event == HOST_SLEEP_EVENT_S3_RESUME) ||
+ (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME))
+ buf.msg.insize = sizeof(buf.u.resp1);
+
+ buf.msg.version = 1;
+
+ } else {
+ buf.u.req0.sleep_event = sleep_event;
+ buf.msg.outsize = sizeof(buf.u.req0);
+ }
buf.msg.command = EC_CMD_HOST_SLEEP_EVENT;
- buf.msg.version = 0;
- buf.msg.outsize = sizeof(buf.req);
- return cros_ec_cmd_xfer(ec_dev, &buf.msg);
+ ret = cros_ec_cmd_xfer(ec_dev, &buf.msg);
+
+ /* For now, report failure to transition to S0ix with a warning. */
+ if (ret >= 0 && ec_dev->host_sleep_v1 &&
+ (sleep_event == HOST_SLEEP_EVENT_S0IX_RESUME))
+ WARN_ONCE(buf.u.resp1.resume_response.sleep_transitions &
+ EC_HOST_RESUME_SLEEP_TIMEOUT,
+ "EC detected sleep transition timeout. Total slp_s0 transitions: %d",
+ buf.u.resp1.resume_response.sleep_transitions &
+ EC_HOST_RESUME_SLEEP_TRANSITIONS_MASK);
+
+ return ret;
}
int cros_ec_register(struct cros_ec_device *ec_dev)