summaryrefslogtreecommitdiff
path: root/power
diff options
context:
space:
mode:
Diffstat (limited to 'power')
-rw-r--r--power/common.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/power/common.c b/power/common.c
index 637a367854..f5091d795c 100644
--- a/power/common.c
+++ b/power/common.c
@@ -77,18 +77,33 @@ static int pause_in_s5;
#endif
static bool want_reboot_ap_at_g3;/* Want to reboot AP from G3? */
+/* Want to reboot AP from G3 with delay? */
+static uint64_t reboot_ap_at_g3_delay;
static enum ec_status
host_command_reboot_ap_on_g3(struct host_cmd_handler_args *args)
{
+ const struct ec_params_reboot_ap_on_g3_v1 *cmd = args->params;
+
/* Store request for processing at g3 */
want_reboot_ap_at_g3 = true;
+ switch (args->version) {
+ case 0:
+ break;
+ case 1:
+ /* Store user specified delay to wait in G3 state */
+ reboot_ap_at_g3_delay = cmd->reboot_ap_at_g3_delay;
+ break;
+ default:
+ return EC_RES_INVALID_PARAM;
+ }
+
return EC_RES_SUCCESS;
}
DECLARE_HOST_COMMAND(EC_CMD_REBOOT_AP_ON_G3,
host_command_reboot_ap_on_g3,
- EC_VER_MASK(0));
+ EC_VER_MASK(0) | EC_VER_MASK(1));
__overridable int power_signal_get_level(enum gpio_signal signal)
{
@@ -419,8 +434,19 @@ static enum power_state power_common_state(enum power_state state)
switch (state) {
case POWER_G3:
if (want_g3_exit || want_reboot_ap_at_g3) {
+ uint64_t i;
+
want_g3_exit = 0;
want_reboot_ap_at_g3 = false;
+ reboot_ap_at_g3_delay = reboot_ap_at_g3_delay * MSEC;
+ /*
+ * G3->S0 transition should happen only after the
+ * user specified delay. Hence, wait until the
+ * user specified delay times out.
+ */
+ for (i = 0; i < reboot_ap_at_g3_delay; i += 100)
+ msleep(100);
+ reboot_ap_at_g3_delay = 0;
return POWER_G3S5;
}