summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ec_commands.h16
-rw-r--r--power/common.c28
-rw-r--r--util/ectool.c26
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);
}