diff options
-rw-r--r-- | include/ec_commands.h | 16 | ||||
-rw-r--r-- | power/common.c | 28 | ||||
-rw-r--r-- | util/ectool.c | 26 |
3 files changed, 61 insertions, 9 deletions
diff --git a/include/ec_commands.h b/include/ec_commands.h index 02e8dab7f2..f1aa73f7f2 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -6033,13 +6033,21 @@ struct ec_response_locate_chip { * * This command is used for validation purpose, where the AP needs to be * returned back to S0 state from G3 state without using the servo to trigger - * wake events.For this,there is no request or response struct. - * - * Order of command usage: - * ectool reboot_ap_on_g3 && shutdown -h now + * wake events. + * - With command version 0: + * AP reboots immediately from G3 + * command usage: ectool reboot_ap_on_g3 && shutdown -h now + * - With command version 1: + * AP reboots after the user specified delay + * command usage: ectool reboot_ap_on_g3 [<delay>] && shutdown -h now */ #define EC_CMD_REBOOT_AP_ON_G3 0x0127 +struct ec_params_reboot_ap_on_g3_v1 { + /* configurable delay in seconds in G3 state */ + uint32_t reboot_ap_at_g3_delay; +} __ec_align4; + /*****************************************************************************/ /* Get PD port capabilities * 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; } diff --git a/util/ectool.c b/util/ectool.c index 5a0ba609e9..8c6fbdfb61 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -259,9 +259,10 @@ const char help_str[] = " reboot_ec <RO|RW|cold|hibernate|hibernate-clear-ap-off|disable-jump|cold-ap-off>" " [at-shutdown|switch-slot]\n" " Reboot EC to RO or RW\n" - " reboot_ap_on_g3\n" - " Requests that the EC will automatically reboot the AP the next time\n" - " we enter the G3 power state.\n" + " reboot_ap_on_g3 [<delay>]\n" + " Requests that the EC will automatically reboot the AP after a\n" + " configurable number of seconds the next time we enter the G3\n" + " power state.\n" " rollbackinfo\n" " Print rollback block information\n" " rtcget\n" @@ -1196,9 +1197,26 @@ int cmd_reboot_ec(int argc, char *argv[]) int cmd_reboot_ap_on_g3(int argc, char *argv[]) { + struct ec_params_reboot_ap_on_g3_v1 p; int rv; + char *e; + int cmdver; + + if (argc < 2) { + p.reboot_ap_at_g3_delay = 0; + } else { + p.reboot_ap_at_g3_delay = strtol(argv[1], &e, 0); + if (e && *e) { + fprintf(stderr, "invalid number\n"); + return -1; + } + } + if (ec_cmd_version_supported(EC_CMD_REBOOT_AP_ON_G3, 1)) + cmdver = 1; + else + cmdver = 0; - rv = ec_command(EC_CMD_REBOOT_AP_ON_G3, 0, NULL, 0, NULL, 0); + rv = ec_command(EC_CMD_REBOOT_AP_ON_G3, cmdver, &p, sizeof(p), NULL, 0); return (rv < 0 ? rv : 0); } |