summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivya Sasidharan <divya.s.sasidharan@intel.com>2022-01-10 14:44:18 -0800
committerCommit Bot <commit-bot@chromium.org>2022-02-15 00:51:32 +0000
commit3c14aea27e5eb8e598287ee5079d8677197b1ae4 (patch)
treeb48a86c08f93de03c8ed078c1eabe79d9b674523
parent9babbbe5be6ae765cd76f59356e5de682f6e3195 (diff)
downloadchrome-ec-3c14aea27e5eb8e598287ee5079d8677197b1ae4.tar.gz
zephyr: subsys/ap_pwrseq: Add shutdown sequence and console commands
* This adds shutdown handling without monitoring signals. * Adds console commands apreset, powerup, apshutdown, powerinfo for debug. BUG=b:203446068 BRANCH=None TEST=zmake testall; make buildall; tested on brya, AP goes to G3 with apshutdown command, boots up with reboot. Change-Id: I89e0fd90371c84d8538e0fdb7258841038217a9b Signed-off-by: Divya Sasidharan <divya.s.sasidharan@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3378893 Reviewed-by: Andrew McRae <amcrae@google.com>
-rw-r--r--zephyr/subsys/ap_pwrseq/CMakeLists.txt2
-rw-r--r--zephyr/subsys/ap_pwrseq/Kconfig9
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h17
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h9
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c70
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c43
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c19
7 files changed, 165 insertions, 4 deletions
diff --git a/zephyr/subsys/ap_pwrseq/CMakeLists.txt b/zephyr/subsys/ap_pwrseq/CMakeLists.txt
index c1761e6824..f08bb3e476 100644
--- a/zephyr/subsys/ap_pwrseq/CMakeLists.txt
+++ b/zephyr/subsys/ap_pwrseq/CMakeLists.txt
@@ -3,4 +3,6 @@
zephyr_include_directories(include)
zephyr_sources_ifdef(CONFIG_X86_NON_DSX_PWRSEQ
x86_non_dsx_common_pwrseq_sm_handler.c)
+zephyr_sources_ifdef(CONFIG_X86_NON_DSX_PWRSEQ_CONSOLE
+ x86_non_dsx_common_pwrseq_console.c)
zephyr_sources_ifdef(CONFIG_X86_NON_DSX_PWRSEQ_ADL x86_non_dsx_adlp_pwrseq_sm.c)
diff --git a/zephyr/subsys/ap_pwrseq/Kconfig b/zephyr/subsys/ap_pwrseq/Kconfig
index 6d2b7ddfb2..4367f0b11a 100644
--- a/zephyr/subsys/ap_pwrseq/Kconfig
+++ b/zephyr/subsys/ap_pwrseq/Kconfig
@@ -27,6 +27,15 @@ config X86_NON_DSX_PWRSEQ_ADL
This enables AP power sequecing support for Intel Alderlake
family of chipset.
+config X86_NON_DSX_PWRSEQ_CONSOLE
+ bool "Console commands for x86 Non Deep Sx power sequencing"
+ depends on X86_NON_DSX_PWRSEQ
+ default n
+ help
+ This option enables Non Deep Sleep Well power sequencing shell
+ console commands to debug.
+
+
config X86_NON_DSW_PWRSEQ_STACK_SIZE
int "AP pwrseq stack size (in bytes)"
default 1024
diff --git a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h
index b468508c37..d46a2183fa 100644
--- a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h
+++ b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h
@@ -55,6 +55,23 @@ enum power_states_ndsx {
SYS_POWER_STATE_S0S3,
};
+/*
+ * AP hard shutdowns are logged on the same path as resets.
+ */
+enum pwrseq_chipset_shutdown_reason {
+ PWRSEQ_CHIPSET_SHUTDOWN_POWERFAIL,
+ /* Forcing a shutdown as part of EC initialization */
+ PWRSEQ_CHIPSET_SHUTDOWN_INIT,
+ /* Forcing shutdown with command */
+ PWRSEQ_CHIPSET_SHUTDOWN_CONSOLE_CMD,
+ /* Forcing a shutdown to effect entry to G3. */
+ PWRSEQ_CHIPSET_SHUTDOWN_G3,
+ /* Force a chipset shutdown from the power button through EC */
+ PWRSEQ_CHIPSET_SHUTDOWN_BUTTON,
+
+ PWRSEQ_CHIPSET_SHUTDOWN_COUNT,
+};
+
/* This encapsulates the attributes of the state machine */
struct pwrseq_context {
/* On power-on start boot up sequence */
diff --git a/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h
index 4212443366..fe1aae194f 100644
--- a/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h
+++ b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h
@@ -42,8 +42,15 @@ struct common_pwrseq_config {
enum power_states_ndsx chipset_pwr_sm_run(
enum power_states_ndsx curr_state,
const struct common_pwrseq_config *com_cfg);
-void init_chipset_pwr_seq_state(void);
void all_sig_pass_thru_handler(void);
+void chipset_force_shutdown(enum pwrseq_chipset_shutdown_reason reason,
+ const struct common_pwrseq_config *com_cfg);
+void chipset_reset(enum pwrseq_chipset_shutdown_reason reason);
void common_rsmrst_pass_thru_handler(void);
+void init_chipset_pwr_seq_state(void);
+enum power_states_ndsx pwr_sm_get_state(void);
+void apshutdown(void);
+
+extern const char pwrsm_dbg[][25];
#endif /* __X86_NON_DSX_COMMON_H__ */
diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c
index fed8240788..c579a86f32 100644
--- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c
@@ -165,6 +165,17 @@ void s0_action_handler(const struct common_pwrseq_config *com_cfg)
generate_sys_pwrok_handler(com_cfg);
}
+/* This should be overridden if there is no power sequencer chip */
+__attribute__((weak)) int intel_x86_get_pg_ec_dsw_pwrok(
+ const struct common_pwrseq_config *com_cfg)
+{
+#if PWRSEQ_GPIO_PRESENT(pg_ec_dsw_pwroks_gpios)
+ return gpio_pin_get_dt(&com_cfg->pg_ec_dsw_pwrok);
+#else
+ return 0;
+#endif
+}
+
void intel_x86_sys_reset_delay(void)
{
/*
@@ -174,6 +185,65 @@ void intel_x86_sys_reset_delay(void)
k_msleep(chip_cfg.sys_reset_delay_ms);
}
+void chipset_reset(enum pwrseq_chipset_shutdown_reason reason)
+{
+ /*
+ * Irrespective of cold_reset value, always toggle SYS_RESET_L to
+ * perform a chipset reset. RCIN# which was used earlier to trigger
+ * a warm reset is known to not work in certain cases where the CPU
+ * is in a bad state (crbug.com/721853).
+ *
+ * The EC cannot control warm vs cold reset of the chipset using
+ * SYS_RESET_L; it's more of a request.
+ */
+ LOG_DBG("%s: %d", __func__, reason);
+
+ /*
+ * Toggling SYS_RESET_L will not have any impact when it's already
+ * low (i,e. Chipset is in reset state).
+ */
+ if (gpio_pin_get_dt(&(chip_cfg.sys_rst_l)) == 0) {
+ LOG_DBG("Chipset is in reset state");
+ return;
+ }
+
+ gpio_pin_set_dt(&(chip_cfg.sys_rst_l), 0);
+ intel_x86_sys_reset_delay();
+ gpio_pin_set_dt(&(chip_cfg.sys_rst_l), 1);
+}
+
+void chipset_force_shutdown(enum pwrseq_chipset_shutdown_reason reason,
+ const struct common_pwrseq_config *com_cfg)
+{
+ int timeout_ms = 50;
+
+ /* TODO: below
+ * report_ap_reset(reason);
+ */
+
+ /* Turn off RMSRST_L to meet tPCH12 */
+ gpio_pin_set_dt(&com_cfg->ec_pch_rsmrst_odl, 0);
+
+ /* Turn off S5 rails */
+ gpio_pin_set_dt(&com_cfg->enable_pp5000_a, 0);
+
+ /*
+ * TODO(b/179519791): Replace this wait with
+ * power_wait_signals_timeout()
+ */
+ /* Now wait for DSW_PWROK and RSMRST_ODL to go away. */
+ while (intel_x86_get_pg_ec_dsw_pwrok(com_cfg) &&
+ gpio_pin_get_dt(&com_cfg->pg_ec_rsmrst_odl) &&
+ (timeout_ms > 0)) {
+ k_msleep(1);
+ timeout_ms--;
+ };
+
+ if (!timeout_ms)
+ LOG_DBG("DSW_PWROK or RSMRST_ODL didn't go low! Assuming G3.");
+}
+
+
void g3s5_action_handler(const struct common_pwrseq_config *com_cfg)
{
gpio_pin_set_dt(&com_cfg->enable_pp5000_a, 1);
diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c
new file mode 100644
index 0000000000..7d9ac38541
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c
@@ -0,0 +1,43 @@
+/* Copyright 2022 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <shell/shell.h>
+#include <x86_non_dsx_common_pwrseq_sm_handler.h>
+
+LOG_MODULE_DECLARE(ap_pwrseq, 4);
+
+/* Console commands */
+static int powerinfo_handler(const struct shell *shell, size_t argc,
+ char **argv)
+{
+ int state;
+
+ state = pwr_sm_get_state();
+ shell_fprintf(shell, SHELL_INFO, "Power state = %d (%s)\n",
+ state, pwrsm_dbg[state]);
+ return 0;
+}
+
+SHELL_CMD_REGISTER(powerinfo, NULL, NULL, powerinfo_handler);
+
+static int apshutdown_handler(const struct shell *shell, size_t argc,
+ char **argv)
+{
+ apshutdown();
+ return 0;
+}
+
+SHELL_CMD_REGISTER(apshutdown, NULL, NULL, apshutdown_handler);
+
+static int apreset_handler(const struct shell *shell, size_t argc,
+ char **argv)
+{
+ chipset_reset(PWRSEQ_CHIPSET_SHUTDOWN_CONSOLE_CMD);
+ return 0;
+}
+
+SHELL_CMD_REGISTER(apreset, NULL, NULL, apreset_handler);
+
+/* End of console commands */
diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c
index cdb4e63cdd..8c23b4de8a 100644
--- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c
@@ -132,6 +132,15 @@ void pwr_sm_set_state(enum power_states_ndsx new_state)
pwrseq_ctx.power_state = new_state;
}
+void apshutdown(void)
+{
+ if (pwr_sm_get_state() != SYS_POWER_STATE_G3) {
+ chipset_force_shutdown(PWRSEQ_CHIPSET_SHUTDOWN_CONSOLE_CMD,
+ &com_cfg);
+ pwr_sm_set_state(SYS_POWER_STATE_G3);
+ }
+}
+
/* Check RSMRST is fine to move from S5 to higher state */
int check_rsmrst_ok(void)
{
@@ -184,7 +193,11 @@ static int common_pwr_sm_run(int state)
rsmrst_pass_thru_handler();
return SYS_POWER_STATE_S5S4;
}
- break;
+ return SYS_POWER_STATE_S5G3;
+
+ case SYS_POWER_STATE_S5G3:
+ chipset_force_shutdown(PWRSEQ_CHIPSET_SHUTDOWN_G3, &com_cfg);
+ return SYS_POWER_STATE_G3;
case SYS_POWER_STATE_S5S4:
/* Check if the PCH has come out of suspend state */
@@ -192,7 +205,8 @@ static int common_pwr_sm_run(int state)
LOG_DBG("RSMRST is ok");
return SYS_POWER_STATE_S4;
}
- break;
+ LOG_DBG("RSMRST is not ok");
+ return SYS_POWER_STATE_S5;
case SYS_POWER_STATE_S4:
return SYS_POWER_STATE_S3;
@@ -216,7 +230,6 @@ static int common_pwr_sm_run(int state)
case SYS_POWER_STATE_S4S5:
case SYS_POWER_STATE_S3S4:
case SYS_POWER_STATE_S0S3:
- case SYS_POWER_STATE_S5G3:
break;
default: