summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernardo Perez Priego <bernardo.perez.priego@intel.com>2022-11-01 18:56:04 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2023-03-24 00:32:52 +0000
commitda4cd3da3d100c62c844c759103133130bf064d0 (patch)
treeafbda8e939e1234e999c1d20937199df527d8437
parent66dc56dc229c5abddd18296ddfad0e7f69218799 (diff)
downloadchrome-ec-stabilize-15395.B-main.tar.gz
ap_pwrseq: Adapt power interface components to AP Power Sequence driverstabilize-15395.B-main
This CL make other components to follow AP Power Sequence driver. BUG=b:217952699 BRANCH=none TEST=zmake build Change-Id: I9d528fadd3074bfa9a2e9d1f36cfdeaf45015579 Signed-off-by: Bernardo Perez Priego <bernardo.perez.priego@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3996453 Reviewed-by: Peter Marheine <pmarheine@chromium.org> Commit-Queue: Peter Marheine <pmarheine@chromium.org> Tested-by: Peter Marheine <pmarheine@chromium.org>
-rw-r--r--zephyr/app/ec/ec_app_main.c2
-rw-r--r--zephyr/include/ap_power/ap_power_events.h2
-rw-r--r--zephyr/include/ap_power/ap_power_interface.h8
-rw-r--r--zephyr/include/ap_power/ap_pwrseq.h14
-rw-r--r--zephyr/shim/src/power_host_sleep_api.c31
-rw-r--r--zephyr/subsys/ap_pwrseq/ap_power_interface.c64
-rw-r--r--zephyr/subsys/ap_pwrseq/ap_pwrseq.c2
-rw-r--r--zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h8
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h2
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h12
-rw-r--r--zephyr/subsys/ap_pwrseq/power_host_sleep.c28
-rw-r--r--zephyr/subsys/ap_pwrseq/power_signals.c13
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c84
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c5
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c12
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c147
16 files changed, 394 insertions, 40 deletions
diff --git a/zephyr/app/ec/ec_app_main.c b/zephyr/app/ec/ec_app_main.c
index 120003b7bc..6b8e113728 100644
--- a/zephyr/app/ec/ec_app_main.c
+++ b/zephyr/app/ec/ec_app_main.c
@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
-#include "ap_power/ap_pwrseq.h"
+#include "ap_power/ap_power_interface.h"
#include "button.h"
#include "chipset.h"
#include "cros_board_info.h"
diff --git a/zephyr/include/ap_power/ap_power_events.h b/zephyr/include/ap_power/ap_power_events.h
index 8a6a9764de..f729c68e9e 100644
--- a/zephyr/include/ap_power/ap_power_events.h
+++ b/zephyr/include/ap_power/ap_power_events.h
@@ -11,6 +11,8 @@
#ifndef __AP_POWER_AP_EVENTS_H__
#define __AP_POWER_AP_EVENTS_H__
+#include <ap_power/ap_power.h>
+
/**
* @brief Dispatch callbacks for an event.
*
diff --git a/zephyr/include/ap_power/ap_power_interface.h b/zephyr/include/ap_power/ap_power_interface.h
index d2808f6075..9a36091deb 100644
--- a/zephyr/include/ap_power/ap_power_interface.h
+++ b/zephyr/include/ap_power/ap_power_interface.h
@@ -9,7 +9,6 @@
*
* Defines the interface to the AP power sequence module,
* which includes:
- * - enums for the power state of the AP
* - enums for the power state mask of the AP
* - enums indicating the reason for shutdown
* - enums for providing control values
@@ -28,6 +27,7 @@
#include <zephyr/sys/util.h>
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
/**
* @brief System power states for Non Deep Sleep Well
* EC is an always on device in a Non Deep Sx system except when EC
@@ -84,6 +84,7 @@ enum power_states_ndsx {
SYS_POWER_STATE_S0S0ix,
#endif
};
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
/**
* @brief Represents the state of the AP as a mask.
@@ -218,4 +219,9 @@ void ap_power_force_shutdown(enum ap_power_shutdown_reason reason);
*/
void ap_power_init_reset_log(void);
+/**
+ * @brief Starts the AP power sequence thread.
+ */
+void ap_pwrseq_task_start(void);
+
#endif /* __AP_POWER_AP_POWER_INTERFACE_H__ */
diff --git a/zephyr/include/ap_power/ap_pwrseq.h b/zephyr/include/ap_power/ap_pwrseq.h
index f7324b0f6c..813b4f231b 100644
--- a/zephyr/include/ap_power/ap_pwrseq.h
+++ b/zephyr/include/ap_power/ap_pwrseq.h
@@ -8,10 +8,9 @@
#include <zephyr/device.h>
#include <zephyr/kernel.h>
-/** Starts the AP power sequence thread */
-void ap_pwrseq_task_start(void);
-
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
void ap_pwrseq_wake(void);
+#else
#ifdef __cplusplus
extern "C" {
@@ -31,7 +30,13 @@ extern "C" {
AP_POWER_SUB_STATE_ENUM_DEF_WITH_COMMA)), \
())))
-/** @brief AP power sequence valid power states. */
+/**
+ * @brief AP power sequence valid power states.
+ *
+ * Note: States enum list MUST remain arranged from the lowest to the highest
+ * power state.
+ *
+ **/
/* clang-format off */
enum ap_pwrseq_state {
AP_POWER_STATE_UNINIT, /* EC and AP are Uninitialized */
@@ -203,4 +208,5 @@ int ap_pwrseq_register_state_exit_callback(
#ifdef __cplusplus
}
#endif
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
#endif /* _AP_PWRSEQ_H_ */
diff --git a/zephyr/shim/src/power_host_sleep_api.c b/zephyr/shim/src/power_host_sleep_api.c
index 99d535bdff..95d9496782 100644
--- a/zephyr/shim/src/power_host_sleep_api.c
+++ b/zephyr/shim/src/power_host_sleep_api.c
@@ -7,6 +7,7 @@
#include <ap_power/ap_power_interface.h>
#include <power_host_sleep.h>
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
static enum power_state
translate_ap_power_state(enum power_states_ndsx ap_power_state)
{
@@ -34,6 +35,36 @@ int ap_power_get_lazy_wake_mask(enum power_states_ndsx state,
return -EINVAL;
return get_lazy_wake_mask(st, mask);
}
+#else
+#include "ap_power/ap_pwrseq.h"
+
+static enum power_state
+translate_ap_power_state(enum ap_pwrseq_state ap_power_state)
+{
+ switch (ap_power_state) {
+ case AP_POWER_STATE_S5:
+ return POWER_S5;
+ case AP_POWER_STATE_S3:
+ return POWER_S3;
+#if CONFIG_AP_PWRSEQ_S0IX
+ case AP_POWER_STATE_S0IX:
+ return POWER_S0ix;
+#endif
+ default:
+ return 0;
+ }
+}
+
+int ap_power_get_lazy_wake_mask(enum ap_pwrseq_state state, host_event_t *mask)
+{
+ enum power_state st;
+
+ st = translate_ap_power_state(state);
+ if (!st)
+ return -EINVAL;
+ return get_lazy_wake_mask(st, mask);
+}
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
#if CONFIG_AP_PWRSEQ_HOST_SLEEP
void power_chipset_handle_host_sleep_event(enum host_sleep_event state,
diff --git a/zephyr/subsys/ap_pwrseq/ap_power_interface.c b/zephyr/subsys/ap_pwrseq/ap_power_interface.c
index 1461ed139b..684bcbb5e0 100644
--- a/zephyr/subsys/ap_pwrseq/ap_power_interface.c
+++ b/zephyr/subsys/ap_pwrseq/ap_power_interface.c
@@ -8,6 +8,7 @@
LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
bool ap_power_in_state(enum ap_power_state_mask state_mask)
{
int need_mask = 0;
@@ -114,6 +115,69 @@ void ap_power_exit_hardoff(void)
return;
request_start_from_g3();
}
+#else
+bool ap_power_in_state(enum ap_power_state_mask state_mask)
+{
+ /*
+ * PWRSEQ_DRIVER will only expose stable power states (transitions
+ * occur automatically and are not visible to API consumers), so
+ * return ap_power_in_or_transitioning_to_state since it is
+ * equivalent to this function.
+ */
+ return ap_power_in_or_transitioning_to_state(state_mask);
+}
+
+bool ap_power_in_or_transitioning_to_state(enum ap_power_state_mask state_mask)
+{
+ const struct device *dev = ap_pwrseq_get_instance();
+
+ switch (ap_pwrseq_get_current_state(dev)) {
+ case AP_POWER_STATE_G3:
+ return state_mask & AP_POWER_STATE_HARD_OFF;
+ case AP_POWER_STATE_S5:
+ return state_mask & AP_POWER_STATE_SOFT_OFF;
+ case AP_POWER_STATE_S3:
+ case AP_POWER_STATE_S4:
+ return state_mask & AP_POWER_STATE_SUSPEND;
+#if CONFIG_AP_PWRSEQ_S0IX
+ case AP_POWER_STATE_S0IX:
+ return state_mask & AP_POWER_STATE_STANDBY;
+#endif
+ case AP_POWER_STATE_S0:
+ return state_mask & AP_POWER_STATE_ON;
+ default:
+ break;
+ }
+ /* Unknown power state; return false. */
+ return 0;
+}
+
+void ap_power_exit_hardoff(void)
+{
+ const struct device *dev = ap_pwrseq_get_instance();
+ enum ap_pwrseq_state power_state;
+
+ ap_pwrseq_state_lock(dev);
+ /*
+ * If not in the soft-off state, hard-off state, or headed there,
+ * nothing to do.
+ */
+ power_state = ap_pwrseq_get_current_state(dev);
+ if (power_state == AP_POWER_STATE_G3 ||
+ power_state == AP_POWER_STATE_S5) {
+ request_start_from_g3();
+ }
+
+ ap_pwrseq_state_unlock(dev);
+}
+
+void ap_pwrseq_task_start(void)
+{
+ const struct device *dev = ap_pwrseq_get_instance();
+
+ ap_pwrseq_start(dev, chipset_pwr_seq_get_state());
+}
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
void ap_power_init_reset_log(void)
{
diff --git a/zephyr/subsys/ap_pwrseq/ap_pwrseq.c b/zephyr/subsys/ap_pwrseq/ap_pwrseq.c
index c02ec88363..6960938205 100644
--- a/zephyr/subsys/ap_pwrseq/ap_pwrseq.c
+++ b/zephyr/subsys/ap_pwrseq/ap_pwrseq.c
@@ -9,7 +9,7 @@
#include <zephyr/logging/log.h>
#include <zephyr/sys/atomic.h>
-LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);
+LOG_MODULE_REGISTER(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);
#define AP_PWRSEQ_EVENT_MASK GENMASK(AP_PWRSEQ_EVENT_COUNT - 1, 0)
#define AP_PWRSEQ_STATES_MASK GENMASK(AP_POWER_STATE_COUNT - 1, 0)
diff --git a/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h b/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h
index 7251f96b76..e615f634b8 100644
--- a/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h
+++ b/zephyr/subsys/ap_pwrseq/include/ap_power_host_sleep.h
@@ -9,6 +9,10 @@
#include <ap_power/ap_power_interface.h>
#include <power_host_sleep.h>
+#ifdef CONFIG_AP_PWRSEQ_DRIVER
+#include "ap_power/ap_pwrseq.h"
+#endif
+
/*
* Deferred call to set active mask according to current power state
*/
@@ -22,8 +26,12 @@ void ap_power_set_active_wake_mask(void);
*
* @return 0 for success; -EINVAL if power state is not S3/S5/S0ix
*/
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
int ap_power_get_lazy_wake_mask(enum power_states_ndsx state,
host_event_t *mask);
+#else
+int ap_power_get_lazy_wake_mask(enum ap_pwrseq_state state, host_event_t *mask);
+#endif
#if CONFIG_AP_PWRSEQ_S0IX
/* For S0ix path, flag to notify sleep change */
diff --git a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h
index 75390b5005..b36b7f7714 100644
--- a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h
+++ b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h
@@ -13,10 +13,12 @@
#include <power_signals.h>
#include <x86_power_signals.h>
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
/* This encapsulates the attributes of the state machine */
struct pwrseq_context {
/* On power-on start boot up sequence */
enum power_states_ndsx power_state;
};
+#endif
#endif /* __X86_COMMON_PWRSEQ_H__ */
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 9656d8982d..2f9b01fbee 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
@@ -10,20 +10,28 @@
#include <zephyr/kernel.h>
#include <zephyr/types.h>
+#ifdef CONFIG_AP_PWRSEQ_DRIVE
+#include <ap_power/ap_pwrseq.h>
+#else
#include <ap_power/ap_power.h>
#include <ap_power/ap_power_events.h>
+#endif
#include <ap_power_host_sleep.h>
#include <x86_common_pwrseq.h>
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
/* The wait time is ~150 msec, allow for safety margin. */
#define IN_PCH_SLP_SUS_WAIT_TIME_MS 250
enum power_states_ndsx chipset_pwr_sm_run(enum power_states_ndsx curr_state);
-void init_chipset_pwr_seq_state(void);
enum power_states_ndsx chipset_pwr_seq_get_state(void);
-void request_start_from_g3(void);
enum power_states_ndsx pwr_sm_get_state(void);
const char *const pwr_sm_get_state_name(enum power_states_ndsx state);
+#else
+enum ap_pwrseq_state chipset_pwr_seq_get_state(void);
+const char *const pwr_sm_get_state_name(enum ap_pwrseq_state state);
+#endif
+void request_start_from_g3(void);
void apshutdown(void);
void ap_pwrseq_handle_chipset_reset(void);
void set_start_from_g3_delay_seconds(uint32_t d_time);
diff --git a/zephyr/subsys/ap_pwrseq/power_host_sleep.c b/zephyr/subsys/ap_pwrseq/power_host_sleep.c
index 5c91b2503e..96335b066b 100644
--- a/zephyr/subsys/ap_pwrseq/power_host_sleep.c
+++ b/zephyr/subsys/ap_pwrseq/power_host_sleep.c
@@ -25,6 +25,7 @@ LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);
* 4. If state is S0ix and no lazy or active wake mask is set, then use default
* S0ix mask to be compatible with older BIOS versions.
*/
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
void power_update_wake_mask(void)
{
host_event_t wake_mask;
@@ -44,6 +45,28 @@ void power_update_wake_mask(void)
lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, wake_mask);
}
+#else
+void power_update_wake_mask(void)
+{
+ const struct device *dev = ap_pwrseq_get_instance();
+ host_event_t wake_mask;
+ enum ap_pwrseq_state state;
+
+ state = ap_pwrseq_get_current_state(dev);
+
+ if (state == AP_POWER_STATE_S0)
+ wake_mask = 0;
+ else if (lpc_is_active_wm_set_by_host() ||
+ ap_power_get_lazy_wake_mask(state, &wake_mask))
+ return;
+#if CONFIG_AP_PWRSEQ_S0IX
+ if ((state == AP_POWER_STATE_S0IX) && (wake_mask == 0))
+ wake_mask = DEFAULT_WAKE_MASK_S0IX;
+#endif
+
+ lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, wake_mask);
+}
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
static void power_update_wake_mask_deferred(struct k_work *work)
{
@@ -251,7 +274,12 @@ void ap_power_chipset_handle_host_sleep_event(
power_signal_disable(PWR_SLP_S0);
}
#endif /* CONFIG_AP_PWRSEQ_S0IX */
+
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
ap_pwrseq_wake();
+#else
+ ap_pwrseq_post_event(ap_pwrseq_get_instance(), AP_PWRSEQ_EVENT_HOST);
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
}
uint16_t host_get_sleep_timeout(void)
diff --git a/zephyr/subsys/ap_pwrseq/power_signals.c b/zephyr/subsys/ap_pwrseq/power_signals.c
index 765cc95707..84a8b8ad53 100644
--- a/zephyr/subsys/ap_pwrseq/power_signals.c
+++ b/zephyr/subsys/ap_pwrseq/power_signals.c
@@ -11,6 +11,9 @@
#include <zephyr/logging/log.h>
#include <zephyr/sys/atomic.h>
#include <zephyr/toolchain.h>
+#ifdef CONFIG_AP_PWRSEQ_DRIVER
+#include <ap_power/ap_pwrseq.h>
+#endif
#include <ap_power/ap_pwrseq.h>
#include <power_signals.h>
@@ -133,13 +136,23 @@ power_signal_mask_t power_get_signals(void)
return mask | atomic_get(&power_signals);
}
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
void power_signal_interrupt(enum power_signal signal, int value)
{
atomic_set_bit_to(&power_signals, signal, value);
check_debug(signal);
ap_pwrseq_wake();
}
+#else
+void power_signal_interrupt(enum power_signal signal, int value)
+{
+ const struct device *ap_pwrseq_dev = ap_pwrseq_get_instance();
+ atomic_set_bit_to(&power_signals, signal, value);
+ check_debug(signal);
+ ap_pwrseq_post_event(ap_pwrseq_dev, AP_PWRSEQ_EVENT_POWER_SIGNAL);
+}
+#endif
int power_wait_mask_signals_timeout(power_signal_mask_t mask,
power_signal_mask_t want, int timeout)
{
diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c
index e4ce364cb1..e4da35b095 100644
--- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_chipset_power_state.c
@@ -3,6 +3,9 @@
* found in the LICENSE file.
*/
+#ifdef CONFIG_AP_PWRSEQ_DRIVER
+#include <ap_power/ap_pwrseq_sm.h>
+#endif
#include <x86_common_pwrseq.h>
#include <x86_non_dsx_common_pwrseq_sm_handler.h>
@@ -12,6 +15,7 @@ LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);
* Determine the current state of the CPU from the
* power signals.
*/
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
enum power_states_ndsx chipset_pwr_seq_get_state(void)
{
power_signal_mask_t sig = power_get_signals();
@@ -89,3 +93,83 @@ enum power_states_ndsx chipset_pwr_seq_get_state(void)
ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
return SYS_POWER_STATE_G3;
}
+#else
+enum ap_pwrseq_state chipset_pwr_seq_get_state(void)
+{
+ power_signal_mask_t sig;
+
+ sig = power_get_signals();
+ /*
+ * Chip is shut down, G3 state.
+ */
+ if ((sig & MASK_ALL_POWER_GOOD) == 0) {
+ LOG_DBG("All power rails off, G3 state");
+ return AP_POWER_STATE_G3;
+ }
+ /*
+ * Not enough power rails up to read VW signals.
+ * Force a shutdown.
+ */
+ if ((sig & MASK_VW_POWER) != VALUE_VW_POWER) {
+ LOG_ERR("Not enough power signals on (%#x), forcing shutdown",
+ sig);
+ ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
+ return AP_POWER_STATE_G3;
+ }
+
+ /*
+ * Enough power signals are up, so
+ * wait for virtual wire signals to become available.
+ * Not sure how long to wait? 5 seconds total.
+ */
+ for (int delay = 0; delay < 500; k_msleep(10), delay++) {
+#if defined(CONFIG_PLATFORM_EC_HOST_INTERFACE_ESPI_VW_SLP_S3)
+ if (power_signal_get(PWR_SLP_S3) < 0)
+ continue;
+#endif
+#if defined(CONFIG_PLATFORM_EC_HOST_INTERFACE_ESPI_VW_SLP_S4)
+ if (power_signal_get(PWR_SLP_S4) < 0)
+ continue;
+#endif
+#if defined(CONFIG_PLATFORM_EC_HOST_INTERFACE_ESPI_VW_SLP_S5)
+ if (power_signal_get(PWR_SLP_S5) < 0)
+ continue;
+#endif
+ /*
+ * All signals valid.
+ */
+ LOG_DBG("All VW signals valid after %d ms", delay * 10);
+ break;
+ }
+ /* Re-read the power signals */
+ sig = power_get_signals();
+
+ /*
+ * S0, all power OK, no suspend or sleep on.
+ */
+ if ((sig & MASK_S0) == VALUE_S0) {
+ LOG_DBG("CPU in S0 state");
+ return AP_POWER_STATE_S0;
+ }
+ /*
+ * S3, all power OK, PWR_SLP_S3 on.
+ */
+ if ((sig & MASK_S3) == VALUE_S3) {
+ LOG_DBG("CPU in S3 state");
+ return AP_POWER_STATE_S3;
+ }
+ /*
+ * S5, some power signals on, PWR_SLP_S5 on.
+ */
+ if ((sig & MASK_S5) == VALUE_S5) {
+ LOG_DBG("CPU in S5 state");
+ return AP_POWER_STATE_S5;
+ }
+ /*
+ * Unable to determine state, force to G3.
+ */
+ LOG_INF("Unable to determine CPU state (%#x), forcing shutdown", sig);
+ ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
+ return AP_POWER_STATE_G3;
+}
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
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
index 6ac2b5e0ba..a31d9e3f3a 100644
--- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_console.c
@@ -15,7 +15,12 @@ LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);
static int powerinfo_handler(const struct shell *shell, size_t argc,
char **argv)
{
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
enum power_states_ndsx state = pwr_sm_get_state();
+#else
+ const struct device *dev = ap_pwrseq_get_instance();
+ enum ap_pwrseq_state state = ap_pwrseq_get_current_state(dev);
+#endif
shell_fprintf(shell, SHELL_INFO, "power state %d = %s, in 0x%04x\n",
state, pwr_sm_get_state_name(state), power_get_signals());
diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c
index 015cecb502..2e16aba1bb 100644
--- a/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_host_sleep.c
@@ -34,6 +34,7 @@ void power_chipset_handle_sleep_hang(enum sleep_hang_type hang_type)
* wake mask to pretend it did, so that the hang detect event wakes the
* system.
*/
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
if (pwr_sm_get_state() == SYS_POWER_STATE_S0) {
host_event_t sleep_wake_mask;
@@ -41,6 +42,17 @@ void power_chipset_handle_sleep_hang(enum sleep_hang_type hang_type)
&sleep_wake_mask);
lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, sleep_wake_mask);
}
+#else
+ const struct device *dev = ap_pwrseq_get_instance();
+
+ if (ap_pwrseq_get_current_state(dev) == AP_POWER_STATE_S0) {
+ host_event_t sleep_wake_mask;
+
+ ap_power_get_lazy_wake_mask(AP_POWER_STATE_S0IX,
+ &sleep_wake_mask);
+ lpc_set_host_event_mask(LPC_HOST_EVENT_WAKE, sleep_wake_mask);
+ }
+#endif
ccprintf("Warning: Detected sleep hang! Waking host up!");
host_set_single_event(EC_HOST_EVENT_HANG_DETECT);
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 3e33915f8f..829ac13f73 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
@@ -9,18 +9,22 @@
#include <zephyr/init.h>
#include <atomic.h>
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
#include <x86_non_dsx_common_pwrseq_sm_handler.h>
+#else
+#include "ap_power/ap_pwrseq.h"
+#include "ap_power/ap_pwrseq_sm.h"
+#include "x86_non_dsx_common_pwrseq_sm_handler.h"
+#include "zephyr_console_shim.h"
+#endif
-static K_KERNEL_STACK_DEFINE(pwrseq_thread_stack, CONFIG_AP_PWRSEQ_STACK_SIZE);
-static struct k_thread pwrseq_thread_data;
-static struct pwrseq_context pwrseq_ctx = {
- .power_state = SYS_POWER_STATE_UNINIT,
-};
-static struct k_sem pwrseq_sem;
+/* Delay in ms when starting from G3 */
+static uint32_t start_from_g3_delay_ms;
+
+#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND
+static bool in_debug_mode;
+#endif
-static void s5_inactive_timer_handler(struct k_timer *timer);
-/* S5 inactive timer*/
-K_TIMER_DEFINE(s5_inactive_timer, s5_inactive_timer_handler, NULL);
/*
* Flags, may be set/cleared from other threads.
*/
@@ -30,12 +34,18 @@ enum {
FLAGS_MAX,
};
static ATOMIC_DEFINE(flags, FLAGS_MAX);
-/* Delay in ms when starting from G3 */
-static uint32_t start_from_g3_delay_ms;
-#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND
-static bool in_debug_mode;
-#endif
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
+static K_KERNEL_STACK_DEFINE(pwrseq_thread_stack, CONFIG_AP_PWRSEQ_STACK_SIZE);
+static struct k_thread pwrseq_thread_data;
+static struct pwrseq_context pwrseq_ctx = {
+ .power_state = SYS_POWER_STATE_UNINIT,
+};
+static struct k_sem pwrseq_sem;
+
+static void s5_inactive_timer_handler(struct k_timer *timer);
+/* S5 inactive timer*/
+K_TIMER_DEFINE(s5_inactive_timer, s5_inactive_timer_handler, NULL);
LOG_MODULE_REGISTER(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);
@@ -65,6 +75,13 @@ static const char *const pwrsm_dbg[] = {
[SYS_POWER_STATE_S0S0ix] = "S0S0ix",
#endif
};
+#else
+static void x86_non_dsx_timer_handler(struct k_timer *timer);
+
+K_TIMER_DEFINE(x86_non_dsx_timer, x86_non_dsx_timer_handler, NULL);
+
+LOG_MODULE_DECLARE(ap_pwrseq, CONFIG_AP_PWRSEQ_LOG_LEVEL);
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
/*
* Returns true if all signals in mask are valid.
@@ -100,6 +117,7 @@ static inline bool signals_valid_and_off(power_signal_mask_t signals)
return signals_valid(signals) && power_signals_off(signals);
}
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
enum power_states_ndsx pwr_sm_get_state(void)
{
return pwrseq_ctx.power_state;
@@ -149,18 +167,6 @@ void request_start_from_g3(void)
ap_pwrseq_wake();
}
-void ap_power_force_shutdown(enum ap_power_shutdown_reason reason)
-{
-#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND
- /* This prevents force shutdown if debug mode is enabled */
- if (in_debug_mode) {
- LOG_WRN("debug_mode is enabled, preventing force shutdown");
- return;
- }
-#endif /* CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND */
- board_ap_power_force_shutdown();
-}
-
static void s5_inactive_timer_handler(struct k_timer *timer)
{
ap_pwrseq_wake();
@@ -173,11 +179,6 @@ static void shutdown_and_notify(enum ap_power_shutdown_reason reason)
ap_power_ev_send_callbacks(AP_POWER_SHUTDOWN_COMPLETE);
}
-void set_start_from_g3_delay_seconds(uint32_t d_time)
-{
- start_from_g3_delay_ms = d_time * MSEC;
-}
-
void apshutdown(void)
{
if (pwr_sm_get_state() != SYS_POWER_STATE_G3) {
@@ -185,6 +186,88 @@ void apshutdown(void)
pwr_sm_set_state(SYS_POWER_STATE_G3);
}
}
+#else
+const char *const pwr_sm_get_state_name(enum ap_pwrseq_state state)
+{
+ return ap_pwrseq_get_state_str(state);
+}
+
+static void x86_non_dsx_timer_handler(struct k_timer *timer)
+{
+ if (atomic_test_bit(flags, S5_INACTIVE_TIMER_RUNNING)) {
+ ap_pwrseq_post_event(ap_pwrseq_get_instance(),
+ AP_PWRSEQ_EVENT_POWER_TIMEOUT);
+ } else if (atomic_test_bit(flags, START_FROM_G3)) {
+ ap_pwrseq_post_event(ap_pwrseq_get_instance(),
+ AP_PWRSEQ_EVENT_POWER_STARTUP);
+ }
+}
+
+void request_start_from_g3(void)
+{
+ const struct device *dev = ap_pwrseq_get_instance();
+
+ LOG_INF("Request start from G3");
+ /*
+ * If in S5, restart the timer to give the CPU more time
+ * to respond to a power button press (which is presumably
+ * why we are being called). This avoids having the S5
+ * inactivity timer expiring before the AP can process
+ * the power button press and start up.
+ */
+ if (ap_pwrseq_get_current_state(dev) == AP_POWER_STATE_S5 &&
+ AP_PWRSEQ_DT_VALUE(s5_inactivity_timeout)) {
+ k_timer_start(
+ &x86_non_dsx_timer,
+ K_SECONDS(AP_PWRSEQ_DT_VALUE(s5_inactivity_timeout)),
+ K_NO_WAIT);
+ return;
+ }
+
+ atomic_set_bit(flags, START_FROM_G3);
+ if (ap_pwrseq_get_current_state(dev) == AP_POWER_STATE_G3) {
+ if (start_from_g3_delay_ms) {
+ k_timer_start(&x86_non_dsx_timer,
+ K_MSEC(start_from_g3_delay_ms),
+ K_NO_WAIT);
+ start_from_g3_delay_ms = 0;
+ } else {
+ ap_pwrseq_post_event(dev,
+ AP_PWRSEQ_EVENT_POWER_STARTUP);
+ }
+ }
+}
+
+void apshutdown(void)
+{
+ const struct device *dev = ap_pwrseq_get_instance();
+
+ ap_pwrseq_state_lock(dev);
+
+ if (ap_pwrseq_get_current_state(dev) != AP_POWER_STATE_G3) {
+ ap_power_force_shutdown(AP_POWER_SHUTDOWN_G3);
+ }
+
+ ap_pwrseq_state_unlock(dev);
+}
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
+
+void ap_power_force_shutdown(enum ap_power_shutdown_reason reason)
+{
+#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND
+ /* This prevents force shutdown if debug mode is enabled */
+ if (in_debug_mode) {
+ LOG_WRN("debug_mode is enabled, preventing force shutdown");
+ return;
+ }
+#endif /* CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND */
+ board_ap_power_force_shutdown();
+}
+
+void set_start_from_g3_delay_seconds(uint32_t d_time)
+{
+ start_from_g3_delay_ms = d_time * MSEC;
+}
void ap_power_reset(enum ap_power_shutdown_reason reason)
{
@@ -242,6 +325,7 @@ void rsmrst_pass_thru_handler(void)
}
}
+#ifndef CONFIG_AP_PWRSEQ_DRIVER
/* Common power sequencing */
static int common_pwr_sm_run(int state)
{
@@ -666,6 +750,7 @@ static int pwrseq_init(const struct device *dev)
* the signals depend upon, such as GPIO, ADC etc.
*/
SYS_INIT(pwrseq_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
+#endif /* CONFIG_AP_PWRSEQ_DRIVER */
#ifdef CONFIG_AP_PWRSEQ_DEBUG_MODE_COMMAND
/*