summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivya Sasidharan <divya.s.sasidharan@intel.com>2022-01-07 10:37:51 -0800
committerCommit Bot <commit-bot@chromium.org>2022-02-14 20:11:50 +0000
commit2826cac033b6233a96792af9c7171e61fda5e5ac (patch)
tree28e06bb085fda44a12454a85fce5fa5cc8dae532
parentb10b4e0a16b8310e6bd7786615b0497044946eca (diff)
downloadchrome-ec-2826cac033b6233a96792af9c7171e61fda5e5ac.tar.gz
zephyr: subsys/ap_pwrseq: Add inbuilt power sequencing support
Add inbuilt AP power sequencing support. This patch adds power up sequence for AP. Built on top of below reference: https://github.com/zephyrproject-rtos/zephyr/pull/29245 TODO: * b:216764983: Create separate .yaml for common and chipset specific GPIOS. * b:217952699: Subsys to driver model, override to callback implementation change. BUG=b:203446068 BRANCH=None TEST=zmake testall; make buildall; brya boots up to S0 and display is up. Change-Id: I84ce803d4e1b4594dc3f61bd2d8bcd1f94fd2be8 Signed-off-by: Divya Sasidharan <divya.s.sasidharan@intel.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3377810 Reviewed-by: Peter Marheine <pmarheine@chromium.org> Reviewed-by: Andrew McRae <amcrae@google.com>
-rw-r--r--zephyr/CMakeLists.txt1
-rw-r--r--zephyr/Kconfig1
-rw-r--r--zephyr/dts/bindings/power/intel,ap-pwrseq.yaml159
-rw-r--r--zephyr/subsys/CMakeLists.txt3
-rw-r--r--zephyr/subsys/Kconfig5
-rw-r--r--zephyr/subsys/ap_pwrseq/CMakeLists.txt6
-rw-r--r--zephyr/subsys/ap_pwrseq/Kconfig41
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h63
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_non_dsx_adlp_pwrseq_sm.h25
-rw-r--r--zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h49
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_nonpwrseq_sm.c20
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c221
-rw-r--r--zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c290
13 files changed, 884 insertions, 0 deletions
diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt
index 17fd538f3a..712875234a 100644
--- a/zephyr/CMakeLists.txt
+++ b/zephyr/CMakeLists.txt
@@ -91,6 +91,7 @@ endif()
add_subdirectory("app")
add_subdirectory("drivers")
add_subdirectory("emul")
+add_subdirectory("subsys")
add_subdirectory_ifdef(CONFIG_PLATFORM_EC "shim")
# Creates a phony target all.libraries in case you only want to build the
diff --git a/zephyr/Kconfig b/zephyr/Kconfig
index 24fd0d8f3b..06ac209925 100644
--- a/zephyr/Kconfig
+++ b/zephyr/Kconfig
@@ -5,6 +5,7 @@
rsource "app/Kconfig"
rsource "drivers/Kconfig"
rsource "emul/Kconfig"
+rsource "subsys/Kconfig"
if ZTEST
diff --git a/zephyr/dts/bindings/power/intel,ap-pwrseq.yaml b/zephyr/dts/bindings/power/intel,ap-pwrseq.yaml
new file mode 100644
index 0000000000..f584c19df7
--- /dev/null
+++ b/zephyr/dts/bindings/power/intel,ap-pwrseq.yaml
@@ -0,0 +1,159 @@
+ # 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.
+
+description: Common fields for AP power sequence
+
+compatible: "intel,ap-pwrseq"
+
+properties:
+ dsw-pwrok-delay:
+ type: int
+ required: false
+ default: 10
+ description: |
+ Delay to set DSW_PWROK high to PCH after 3.3V rail stable,
+ in milliseconds.
+
+ rsmrst-delay:
+ type: int
+ required: false
+ default: 10
+ description: |
+ Delay to set RSMRST from EC to SoC, in milliseconds.
+
+ sys-pwrok-delay:
+ type: int
+ required: false
+ default: 45
+ description: |
+ Delay from PG_EC_ALL_SYS_PWRGD high to set EC_PCH_SYS_PWROK high,
+ in milliseconds.
+
+ pm-pwrbtn-delay:
+ type: int
+ required: false
+ default: 200
+ description: |
+ Power button delay, in milliseconds.
+
+ pch-pwrok-delay:
+ type: int
+ required: false
+ default: 2
+ description: |
+ Delay in ms from IMVP9_VRRDY high to PCH_PWROK high delay.
+
+ vccst-pwrgd-delay:
+ type: int
+ required: false
+ default: 2
+ description: |
+ Delay in ms from PG_EC_ALL_SYS_PWRGD high
+ to VCCST_PWRGD high.
+
+ sys-reset-delay:
+ type: int
+ required: false
+ default: 32
+ description: Debounce time for SYS_RESET_L.
+
+ vrrdy-timeout:
+ type: int
+ required: false
+ default: 50
+ description: |
+ Timeout in ms for IMVP9_VRRDY high.
+
+ all-sys-pwrgd-timeout:
+ type: int
+ required: false
+ default: 0
+ description: |
+ Timeout in ms for ALL_SYS_PWRGD input to EC to be high.
+
+ wait-signal-timeout:
+ type: int
+ required: false
+ default: 1000
+ description: |
+ Timeout in ms for monitoring power signals.
+
+ pg-ec-dsw-pwrok-gpios:
+ type: phandle-array
+ required: false
+ description: |
+ VR/Circuit input to EC 3.3V power good signal.
+
+ ec-pch-rsmrst-odl-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ EC output to PCH, indicating RSMRST power good signal.
+
+ en-pp5000-s5-gpios:
+ type: phandle-array
+ required: false
+ description: |
+ Output from EC to enable 5V rail.
+
+ pg-ec-rsmrst-odl-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ VR/Circuit input to EC RSMRST power good for
+ VCCPRIM rails and other S5 rails.
+
+ slp-s3-l-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ SLP_S3 signal input to EC for S3 sleep control from SoC.
+
+ pg-ec-all-sys-pwrgd-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ This represents the power good for all
+ the platform voltage rails input to EC.
+
+ sys-rst-l-gpios:
+ type: phandle-array
+ required: false
+ description: |
+ SYS Reset signal output from EC.
+
+ ec-pch-sys-pwrok-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ SYS_PWROK is a generic power good input to the PCH from EC,
+ driven and utilized in a platform specific manner.
+
+ pch-pwrok-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ PCH PWROK assertion indicates all the main PCH
+ primary rails and all the CPU rails are up from EC to PCH.
+
+ imvp9-vrrdy-od-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ IMVP VRRDY input signal to EC indicates that the IMVP
+ start-up sequence is complete.
+
+ vccst-pwrgd-od-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ VCCST PWRGD signal output from EC to indicate that the
+ VCC1P05_PROC/VDDQ power supplies are stable and
+ within specification.
+
+ slp-sus-l-gpios:
+ type: phandle-array
+ required: true
+ description: |
+ SLP_SUS signal from SoC to EC.
diff --git a/zephyr/subsys/CMakeLists.txt b/zephyr/subsys/CMakeLists.txt
new file mode 100644
index 0000000000..4e1389b729
--- /dev/null
+++ b/zephyr/subsys/CMakeLists.txt
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: Apache-2.0
+
+add_subdirectory_ifdef(CONFIG_AP_PWRSEQ ap_pwrseq)
diff --git a/zephyr/subsys/Kconfig b/zephyr/subsys/Kconfig
new file mode 100644
index 0000000000..f35a942afc
--- /dev/null
+++ b/zephyr/subsys/Kconfig
@@ -0,0 +1,5 @@
+# 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.
+
+rsource "ap_pwrseq/Kconfig"
diff --git a/zephyr/subsys/ap_pwrseq/CMakeLists.txt b/zephyr/subsys/ap_pwrseq/CMakeLists.txt
new file mode 100644
index 0000000000..c1761e6824
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/CMakeLists.txt
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: Apache-2.0
+
+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_ADL x86_non_dsx_adlp_pwrseq_sm.c)
diff --git a/zephyr/subsys/ap_pwrseq/Kconfig b/zephyr/subsys/ap_pwrseq/Kconfig
new file mode 100644
index 0000000000..6d2b7ddfb2
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/Kconfig
@@ -0,0 +1,41 @@
+# 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.
+
+menuconfig AP_PWRSEQ
+ bool "AP Power sequencing support"
+ help
+ Enables AP power sequencing support with
+ embedded controller. This includes normal shutdown, critical
+ shutdown and reset handling.
+
+if AP_PWRSEQ
+
+config X86_NON_DSX_PWRSEQ
+ bool
+ default n
+ help
+ This option enables Non Deep Sleep Well power sequencing for
+ Intel x86 chips.
+
+config X86_NON_DSX_PWRSEQ_ADL
+ bool "x86 Non Deep Sx power sequencing on ADL"
+ depends on AP_X86_INTEL_ADL
+ select X86_NON_DSX_PWRSEQ
+ default n
+ help
+ This enables AP power sequecing support for Intel Alderlake
+ family of chipset.
+
+config X86_NON_DSW_PWRSEQ_STACK_SIZE
+ int "AP pwrseq stack size (in bytes)"
+ default 1024
+ help
+ This option specifies the size of the stack used by the
+ AP power sequencing state machine thread handler.
+
+endif
+
+module = AP_PWRSEQ
+module-str = ap_pwrseq
+source "subsys/logging/Kconfig.template.log_config"
diff --git a/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h
new file mode 100644
index 0000000000..b468508c37
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/include/x86_common_pwrseq.h
@@ -0,0 +1,63 @@
+/* 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.
+ */
+
+#ifndef __X86_COMMON_PWRSEQ_H__
+#define __X86_COMMON_PWRSEQ_H__
+
+#include <drivers/espi.h>
+#include <drivers/gpio.h>
+#include <logging/log.h>
+
+/**
+ * @brief System power states for Non Deep Sleep Well
+ * EC is an always on device in a Non Deep Sx system except when EC
+ * is hibernated or all the VRs are turned off.
+ */
+enum power_states_ndsx {
+ /*
+ * Actual power states
+ */
+ /* AP is off & EC is on */
+ SYS_POWER_STATE_G3,
+ /* AP is in soft off state */
+ SYS_POWER_STATE_S5,
+ /* AP is suspended to Non-volatile disk */
+ SYS_POWER_STATE_S4,
+ /* AP is suspended to RAM */
+ SYS_POWER_STATE_S3,
+ /* AP is in active state */
+ SYS_POWER_STATE_S0,
+
+ /*
+ * Intermediate power up states
+ */
+ /* Determine if the AP's power rails are turned on */
+ SYS_POWER_STATE_G3S5,
+ /* Determine if AP is suspended from sleep */
+ SYS_POWER_STATE_S5S4,
+ /* Determine if Suspend to Disk is de-asserted */
+ SYS_POWER_STATE_S4S3,
+ /* Determine if Suspend to RAM is de-asserted */
+ SYS_POWER_STATE_S3S0,
+
+ /*
+ * Intermediate power down states
+ */
+ /* Determine if the AP's power rails are turned off */
+ SYS_POWER_STATE_S5G3,
+ /* Determine if AP is suspended to sleep */
+ SYS_POWER_STATE_S4S5,
+ /* Determine if Suspend to Disk is asserted */
+ SYS_POWER_STATE_S3S4,
+ /* Determine if Suspend to RAM is asserted */
+ SYS_POWER_STATE_S0S3,
+};
+
+/* 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 /* __X86_COMMON_H__ */
diff --git a/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_adlp_pwrseq_sm.h b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_adlp_pwrseq_sm.h
new file mode 100644
index 0000000000..94d6766a72
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_adlp_pwrseq_sm.h
@@ -0,0 +1,25 @@
+/* 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.
+ */
+
+#ifndef __X86_NON_DSX_ADLP_PWRSEQ_SM_H__
+#define __X86_NON_DSX_ADLP_PWRSEQ_SM_H__
+
+#include <x86_common_pwrseq.h>
+#include <x86_non_dsx_common_pwrseq_sm_handler.h>
+
+struct chipset_pwrseq_config {
+ int pch_pwrok_delay_ms;
+ int sys_pwrok_delay_ms;
+ int sys_reset_delay_ms;
+ int vccst_pwrgd_delay_ms;
+ int vrrdy_timeout_ms;
+ int all_sys_pwrgd_timeout;
+ const struct gpio_dt_spec vccst_pwrgd_od;
+ const struct gpio_dt_spec imvp9_vrrdy_od;
+ const struct gpio_dt_spec pch_pwrok;
+ const struct gpio_dt_spec ec_pch_sys_pwrok;
+ const struct gpio_dt_spec sys_rst_l;
+};
+#endif /* __X86_NON_DSX_ADLP_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
new file mode 100644
index 0000000000..4212443366
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/include/x86_non_dsx_common_pwrseq_sm_handler.h
@@ -0,0 +1,49 @@
+/* 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.
+ */
+
+#ifndef __X86_NON_DSX_COMMON_PWRSEQ_SM_HANDLER_H__
+#define __X86_NON_DSX_COMMON_PWRSEQ_SM_HANDLER_H__
+
+#include <x86_common_pwrseq.h>
+
+#define DT_DRV_COMPAT intel_ap_pwrseq
+#define INTEL_COM_POWER_NODE DT_INST(0, intel_ap_pwrseq)
+
+/* Check if the gpio is needed for the power sequence */
+#define PWRSEQ_GPIO_PRESENT(pha) \
+ DT_PHA_HAS_CELL(INTEL_COM_POWER_NODE, pha, flags)
+
+/* Common device tree configurable attributes */
+struct common_pwrseq_config {
+ int pch_dsw_pwrok_delay_ms;
+ int pch_pm_pwrbtn_delay_ms;
+ int pch_rsmrst_delay_ms;
+#if PWRSEQ_GPIO_PRESENT(en_pp5000_s5_gpios)
+ const struct gpio_dt_spec enable_pp5000_a;
+#endif
+#if PWRSEQ_GPIO_PRESENT(en_pp3300_s5_gpios)
+ const struct gpio_dt_spec enable_pp3300_a;
+#endif
+ const struct gpio_dt_spec pg_ec_rsmrst_odl;
+ const struct gpio_dt_spec ec_pch_rsmrst_odl;
+#if PWRSEQ_GPIO_PRESENT(pg_ec_dsw_pwrok_gpios)
+ const struct gpio_dt_spec pg_ec_dsw_pwrok;
+#endif
+#if PWRSEQ_GPIO_PRESENT(ec_soc_dsw_pwrok_gpios)
+ const struct gpio_dt_spec ec_soc_dsw_pwrok;
+#endif
+ const struct gpio_dt_spec slp_s3_l;
+ const struct gpio_dt_spec all_sys_pwrgd;
+ const struct gpio_dt_spec slp_sus_l;
+};
+
+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 common_rsmrst_pass_thru_handler(void);
+
+#endif /* __X86_NON_DSX_COMMON_H__ */
diff --git a/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_nonpwrseq_sm.c b/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_nonpwrseq_sm.c
new file mode 100644
index 0000000000..3f6bfa3027
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_nonpwrseq_sm.c
@@ -0,0 +1,20 @@
+/* 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 <ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.h>
+
+LOG_MODULE_DECLARE(ap_pwrseq, 4);
+
+__override int all_sys_pwrgd_handler(void)
+{
+ /* Add signal handling */
+ return 0;
+}
+
+__override int intel_x86_get_pg_ec_dsw_pwrok(void)
+{
+ /* Add signal handling */
+ return 0;
+}
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
new file mode 100644
index 0000000000..fed8240788
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_adlp_pwrseq_sm.c
@@ -0,0 +1,221 @@
+/* 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 <x86_non_dsx_adlp_pwrseq_sm.h>
+
+LOG_MODULE_DECLARE(ap_pwrseq, 4);
+
+static const struct chipset_pwrseq_config chip_cfg = {
+ .pch_pwrok_delay_ms = DT_INST_PROP(0, pch_pwrok_delay),
+ .sys_pwrok_delay_ms = DT_INST_PROP(0, sys_pwrok_delay),
+ .vccst_pwrgd_delay_ms = DT_INST_PROP(0, vccst_pwrgd_delay),
+ .vrrdy_timeout_ms = DT_INST_PROP(0, vrrdy_timeout),
+ .sys_reset_delay_ms = DT_INST_PROP(0, sys_reset_delay),
+ .all_sys_pwrgd_timeout = DT_INST_PROP(0, all_sys_pwrgd_timeout),
+ .vccst_pwrgd_od = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ vccst_pwrgd_od_gpios),
+ .imvp9_vrrdy_od = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ imvp9_vrrdy_od_gpios),
+ .pch_pwrok = GPIO_DT_SPEC_GET(DT_DRV_INST(0), pch_pwrok_gpios),
+ .ec_pch_sys_pwrok = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ ec_pch_sys_pwrok_gpios),
+ .sys_rst_l = GPIO_DT_SPEC_GET(DT_DRV_INST(0), sys_rst_l_gpios),
+};
+
+void ap_off(void)
+{
+ /* TODO: This could be added as g3action handler */
+ gpio_pin_set_dt(&chip_cfg.vccst_pwrgd_od, 0);
+ gpio_pin_set_dt(&chip_cfg.pch_pwrok, 0);
+ gpio_pin_set_dt(&chip_cfg.ec_pch_sys_pwrok, 0);
+}
+
+/* This should be overridden if there is no power sequencer chip */
+__attribute__((weak)) int intel_x86_get_pg_ec_all_sys_pwrgd(
+ const struct common_pwrseq_config *com_cfg)
+{
+ return gpio_pin_get_dt(&com_cfg->all_sys_pwrgd);
+}
+
+/* Handle ALL_SYS_PWRGD signal
+ * This will be overridden if the custom signal handler is needed
+ */
+__attribute__((weak)) int all_sys_pwrgd_handler(
+ const struct common_pwrseq_config *com_cfg)
+{
+ int retry = 0;
+
+ /* TODO: Add condition for no power sequencer */
+ k_msleep(chip_cfg.all_sys_pwrgd_timeout);
+
+ if (intel_x86_get_pg_ec_all_sys_pwrgd(com_cfg) == 0) {
+ /* Todo: Remove workaround for the retry
+ * without this change the system hits G3 as it detects
+ * ALL_SYS_PWRGD as 0 and then 1 as a glitch
+ */
+ while (!intel_x86_get_pg_ec_all_sys_pwrgd(com_cfg)) {
+ if (++retry > 2) {
+ LOG_ERR("PG_EC_ALL_SYS_PWRGD not ok\n");
+ ap_off();
+ return -1;
+ }
+ k_msleep(10);
+ }
+ }
+
+ /* PG_EC_ALL_SYS_PWRGD is asserted, enable VCCST_PWRGD_OD. */
+
+ if (gpio_pin_get_dt(&chip_cfg.vccst_pwrgd_od) == 0) {
+ k_msleep(chip_cfg.vccst_pwrgd_delay_ms);
+ gpio_pin_set_dt(&chip_cfg.vccst_pwrgd_od, 1);
+ }
+ return 0;
+}
+
+/*
+ * We have asserted VCCST_PWRGO_OD, now wait for the IMVP9.1
+ * to assert IMVP9_VRRDY_OD.
+ *
+ * Returns state of VRRDY.
+ */
+
+static int wait_for_vrrdy(void)
+{
+ int timeout_ms = chip_cfg.vrrdy_timeout_ms;
+
+ for (; timeout_ms > 0; --timeout_ms) {
+ if (gpio_pin_get_dt(&chip_cfg.imvp9_vrrdy_od) != 0)
+ return 1;
+ k_msleep(1);
+ }
+ return 0;
+}
+
+/* PCH_PWROK to PCH from EC */
+int generate_pch_pwrok_handler(void)
+{
+ /* Enable PCH_PWROK, gated by VRRDY. */
+ if (gpio_pin_get_dt(&chip_cfg.pch_pwrok) == 0) {
+ if (wait_for_vrrdy() == 0) {
+ LOG_DBG("Timed out waiting for VRRDY, "
+ "shutting AP off!");
+ ap_off();
+ return -1;
+ }
+ k_msleep(chip_cfg.pch_pwrok_delay_ms);
+ gpio_pin_set_dt(&chip_cfg.pch_pwrok, 1);
+ LOG_DBG("Set PCH_PWROK\n");
+ }
+
+ return 0;
+}
+
+/* Generate SYS_PWROK->SOC if needed by system */
+void generate_sys_pwrok_handler(const struct common_pwrseq_config *com_cfg)
+{
+ /* Enable PCH_SYS_PWROK. */
+ if (gpio_pin_get_dt(&chip_cfg.ec_pch_sys_pwrok) == 0) {
+ k_msleep(chip_cfg.sys_pwrok_delay_ms);
+ /* Check if we lost power while waiting. */
+ if (intel_x86_get_pg_ec_all_sys_pwrgd(com_cfg) == 0) {
+ LOG_DBG("PG_EC_ALL_SYS_PWRGD deasserted, "
+ "shutting AP off!");
+ ap_off();
+ return;
+ }
+ gpio_pin_set_dt(&chip_cfg.ec_pch_sys_pwrok, 1);
+ /* PCH will now release PLT_RST */
+ }
+}
+
+/* Chipset specific power state machine handler */
+
+/* TODO: Separate with and without power sequencer logic here */
+
+void s0_action_handler(const struct common_pwrseq_config *com_cfg)
+{
+ int ret;
+
+ /* Handle DSW_PWROK passthrough */
+ /* This is not needed for alderlake silego, guarded by CONFIG? */
+
+ /* Check ALL_SYS_PWRGD and take action */
+ ret = all_sys_pwrgd_handler(com_cfg);
+ if (ret) {
+ LOG_DBG("ALL_SYS_PWRGD handling failed err= %d\n", ret);
+ return;
+ }
+
+ /* Send PCH_PWROK->SoC if conditions met */
+ /* TODO: There is possibility of EC not needing to generate
+ * this as power sequencer may do it
+ */
+ ret = generate_pch_pwrok_handler();
+ if (ret) {
+ LOG_DBG("PCH_PWROK handling failed err=%d\n", ret);
+ return;
+ }
+
+ /* SYS_PWROK may be optional and the delay must be
+ * configurable as it is variable with platform
+ */
+ /* Send SYS_PWROK->SoC if conditions met */
+ generate_sys_pwrok_handler(com_cfg);
+}
+
+void intel_x86_sys_reset_delay(void)
+{
+ /*
+ * Debounce time for SYS_RESET_L is 16 ms. Wait twice that period
+ * to be safe.
+ */
+ k_msleep(chip_cfg.sys_reset_delay_ms);
+}
+
+void g3s5_action_handler(const struct common_pwrseq_config *com_cfg)
+{
+ gpio_pin_set_dt(&com_cfg->enable_pp5000_a, 1);
+}
+
+void init_chipset_pwr_seq_state(void)
+{
+ int ret = 0;
+
+ /* Configure gpios specific to the chipset */
+ ret |= gpio_pin_configure_dt(&chip_cfg.vccst_pwrgd_od,
+ GPIO_OUTPUT_LOW);
+ ret |= gpio_pin_configure_dt(&chip_cfg.imvp9_vrrdy_od,
+ GPIO_INPUT);
+ ret |= gpio_pin_configure_dt(&chip_cfg.pch_pwrok,
+ GPIO_OUTPUT_LOW);
+ ret |= gpio_pin_configure_dt(&chip_cfg.ec_pch_sys_pwrok,
+ GPIO_OUTPUT_LOW);
+ ret |= gpio_pin_configure_dt(&chip_cfg.sys_rst_l,
+ GPIO_OUTPUT_HIGH);
+
+ if (!ret)
+ LOG_INF("Configuring GPIO complete");
+ else
+ LOG_ERR("Power seq gpio configuration failed\n");
+}
+
+enum power_states_ndsx chipset_pwr_sm_run(enum power_states_ndsx curr_state,
+ const struct common_pwrseq_config *com_cfg)
+{
+/* Add chipset specific state handling if any */
+ switch (curr_state) {
+ case SYS_POWER_STATE_G3S5:
+ g3s5_action_handler(com_cfg);
+ break;
+ case SYS_POWER_STATE_S5:
+ break;
+ case SYS_POWER_STATE_S0:
+ s0_action_handler(com_cfg);
+ break;
+ default:
+ break;
+ }
+ return curr_state;
+}
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
new file mode 100644
index 0000000000..cdb4e63cdd
--- /dev/null
+++ b/zephyr/subsys/ap_pwrseq/x86_non_dsx_common_pwrseq_sm_handler.c
@@ -0,0 +1,290 @@
+/* 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 <x86_non_dsx_common_pwrseq_sm_handler.h>
+
+static K_KERNEL_STACK_DEFINE(pwrseq_thread_stack,
+ CONFIG_X86_NON_DSW_PWRSEQ_STACK_SIZE);
+static struct k_thread pwrseq_thread_data;
+static struct pwrseq_context pwrseq_ctx;
+
+LOG_MODULE_REGISTER(ap_pwrseq, 4);
+
+static const struct common_pwrseq_config com_cfg = {
+ .pch_dsw_pwrok_delay_ms = DT_INST_PROP(0, dsw_pwrok_delay),
+ .pch_pm_pwrbtn_delay_ms = DT_INST_PROP(0, pm_pwrbtn_delay),
+ .pch_rsmrst_delay_ms = DT_INST_PROP(0, rsmrst_delay),
+#if PWRSEQ_GPIO_PRESENT(en_pp5000_s5_gpios)
+ .enable_pp5000_a = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ en_pp5000_s5_gpios),
+#endif
+#if PWRSEQ_GPIO_PRESENT(en_pp3300_s5_gpios)
+ .enable_pp3300_a = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ en_pp3300_s5_gpios),
+#endif
+ .pg_ec_rsmrst_odl = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ pg_ec_rsmrst_odl_gpios),
+ .ec_pch_rsmrst_odl = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ ec_pch_rsmrst_odl_gpios),
+#if PWRSEQ_GPIO_PRESENT(pg_ec_dsw_pwrok_gpios)
+ .pg_ec_dsw_pwrok = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ pg_ec_dsw_pwrok_gpios),
+#endif
+#if PWRSEQ_GPIO_PRESENT(ec_soc_dsw_pwrok_gpios)
+ .ec_soc_dsw_pwrok = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ ec_soc_dsw_pwrok_gpios),
+#endif
+ .slp_s3_l = GPIO_DT_SPEC_GET(DT_DRV_INST(0), slp_s3_l_gpios),
+ .all_sys_pwrgd = GPIO_DT_SPEC_GET(DT_DRV_INST(0),
+ pg_ec_all_sys_pwrgd_gpios),
+ .slp_sus_l = GPIO_DT_SPEC_GET(DT_DRV_INST(0), slp_sus_l_gpios),
+};
+
+#ifdef CONFIG_LOG
+/**
+ * @brief power_state names for debug
+ */
+const char pwrsm_dbg[][25] = {
+ [SYS_POWER_STATE_G3] = "STATE_G3",
+ [SYS_POWER_STATE_S5] = "STATE_S5",
+ [SYS_POWER_STATE_S4] = "STATE_S4",
+ [SYS_POWER_STATE_S3] = "STATE_S3",
+ [SYS_POWER_STATE_S0] = "STATE_S0",
+ [SYS_POWER_STATE_G3S5] = "STATE_G3S5",
+ [SYS_POWER_STATE_S5S4] = "STATE_S5S4",
+ [SYS_POWER_STATE_S4S3] = "STATE_S4S3",
+ [SYS_POWER_STATE_S3S0] = "STATE_S3S0",
+ [SYS_POWER_STATE_S5G3] = "STATE_S5G3",
+ [SYS_POWER_STATE_S4S5] = "STATE_S4S5",
+ [SYS_POWER_STATE_S3S4] = "STATE_S3S4",
+ [SYS_POWER_STATE_S0S3] = "STATE_S0S3",
+};
+#endif
+
+void power_signal_interrupt(void)
+{
+ /* TODO: Add handling */
+}
+
+static int check_power_rails_enabled(void)
+{
+ int out = 1;
+
+#if PWRSEQ_GPIO_PRESENT(en_pp3300_s5_gpios)
+ out &= gpio_pin_get_dt(&com_cfg.enable_pp3300_a);
+#endif
+#if PWRSEQ_GPIO_PRESENT(en_pp5000_s5_gpios)
+ out &= gpio_pin_get_dt(&com_cfg.enable_pp5000_a);
+#endif
+#if PWRSEQ_GPIO_PRESENT(pg_ec_dsw_pwrok_gpios)
+ out &= gpio_pin_get_dt(&com_cfg.pg_ec_dsw_pwrok);
+#endif
+ return out;
+}
+
+static void pwrseq_gpio_init(void)
+{
+ int ret = 0;
+
+ /* Configure the GPIO */
+#if PWRSEQ_GPIO_PRESENT(en_pp5000_s5_gpios)
+ ret = gpio_pin_configure_dt(&com_cfg.enable_pp5000_a,
+ GPIO_OUTPUT_LOW);
+#endif
+#if PWRSEQ_GPIO_PRESENT(en_pp3300_s5_gpios)
+ ret |= gpio_pin_configure_dt(&com_cfg.enable_pp3300_a,
+ GPIO_OUTPUT_LOW);
+#endif
+ ret |= gpio_pin_configure_dt(&com_cfg.pg_ec_rsmrst_odl,
+ GPIO_INPUT);
+ ret |= gpio_pin_configure_dt(&com_cfg.ec_pch_rsmrst_odl,
+ GPIO_OUTPUT_LOW);
+#if PWRSEQ_GPIO_PRESENT(pg_ec_dsw_pwrok_gpios)
+ ret |= gpio_pin_configure_dt(&com_cfg.pg_ec_dsw_pwrok,
+ GPIO_INPUT);
+#endif
+#if PWRSEQ_GPIO_PRESENT(ec_soc_dsw_pwrok_gpios)
+ ret |= gpio_pin_configure_dt(&com_cfg.ec_soc_dsw_pwrok,
+ GPIO_OUTPUT_LOW);
+#endif
+ ret |= gpio_pin_configure_dt(&com_cfg.slp_s3_l, GPIO_INPUT);
+ ret |= gpio_pin_configure_dt(&com_cfg.slp_sus_l, GPIO_INPUT);
+ ret |= gpio_pin_configure_dt(&com_cfg.all_sys_pwrgd, GPIO_INPUT);
+
+ if (!ret)
+ LOG_INF("Configuring GPIO complete");
+ else
+ LOG_ERR("GPIO configure failed\n");
+}
+
+enum power_states_ndsx pwr_sm_get_state(void)
+{
+ return pwrseq_ctx.power_state;
+}
+
+void pwr_sm_set_state(enum power_states_ndsx new_state)
+{
+ /* Add locking mechanism if multiple thread can update it */
+ LOG_DBG("Power state: %s --> %s\n", pwrsm_dbg[pwrseq_ctx.power_state],
+ pwrsm_dbg[new_state]);
+ pwrseq_ctx.power_state = new_state;
+}
+
+/* Check RSMRST is fine to move from S5 to higher state */
+int check_rsmrst_ok(void)
+{
+ /* TODO: Check if this is still intact*/
+ return gpio_pin_get_dt(&com_cfg.pg_ec_rsmrst_odl);
+}
+
+int check_pch_out_of_suspend(void)
+{
+ return gpio_pin_get_dt(&com_cfg.slp_sus_l);
+}
+
+/* Handling RSMRST signal is mostly common across x86 chipsets */
+__attribute__((weak)) void rsmrst_pass_thru_handler(void)
+{
+ /* Handle RSMRST passthrough */
+ /* TODO: Add additional conditions for RSMRST handling */
+ int in_sig_val = gpio_pin_get_dt(&com_cfg.pg_ec_rsmrst_odl);
+ int out_sig_val = gpio_pin_get_dt(&com_cfg.ec_pch_rsmrst_odl);
+
+ if (in_sig_val != out_sig_val) {
+ if (in_sig_val)
+ k_msleep(com_cfg.pch_rsmrst_delay_ms);
+ gpio_pin_set_dt(&com_cfg.ec_pch_rsmrst_odl, in_sig_val);
+ }
+}
+
+/* TODO:
+ * Add power down sequence
+ * Add power signal monitoring
+ * Add logic to suspend and resume the thread
+ */
+static int common_pwr_sm_run(int state)
+{
+ switch (state) {
+ case SYS_POWER_STATE_G3:
+ /* Nothing to do */
+ break;
+
+ case SYS_POWER_STATE_G3S5:
+ /* TODO: Check if we are good to move to S5*/
+ if (check_pch_out_of_suspend())
+ return SYS_POWER_STATE_S5;
+ break;
+
+ case SYS_POWER_STATE_S5:
+ /* If A-rails are stable move to higher state */
+ if (check_power_rails_enabled() && check_rsmrst_ok()) {
+ /* rsmrst is intact */
+ rsmrst_pass_thru_handler();
+ return SYS_POWER_STATE_S5S4;
+ }
+ break;
+
+ case SYS_POWER_STATE_S5S4:
+ /* Check if the PCH has come out of suspend state */
+ if (check_rsmrst_ok()) {
+ LOG_DBG("RSMRST is ok");
+ return SYS_POWER_STATE_S4;
+ }
+ break;
+
+ case SYS_POWER_STATE_S4:
+ return SYS_POWER_STATE_S3;
+
+ case SYS_POWER_STATE_S3:
+ /* AP is out of suspend to RAM */
+ if (gpio_pin_get_dt(&com_cfg.slp_s3_l))
+ return SYS_POWER_STATE_S3S0;
+ break;
+
+ case SYS_POWER_STATE_S3S0:
+ /* All the power rails must be stable */
+ if (gpio_pin_get_dt(&com_cfg.all_sys_pwrgd))
+ return SYS_POWER_STATE_S0;
+ break;
+
+ case SYS_POWER_STATE_S0:
+ /* Stay in S0 */
+ break;
+
+ case SYS_POWER_STATE_S4S5:
+ case SYS_POWER_STATE_S3S4:
+ case SYS_POWER_STATE_S0S3:
+ case SYS_POWER_STATE_S5G3:
+ break;
+
+ default:
+ break;
+ }
+
+ return state;
+}
+
+static void pwrseq_loop_thread(void *p1, void *p2, void *p3)
+{
+ int32_t t_wait_ms = 10;
+ enum power_states_ndsx curr_state, new_state;
+
+ while (1) {
+ curr_state = pwr_sm_get_state();
+ /* Run chipset specific state machine */
+ new_state = chipset_pwr_sm_run(curr_state, &com_cfg);
+
+ /*
+ * Run common power state machine
+ * if the state has changed in chipset state
+ * machine then skip running common state
+ * machine
+ */
+ if (curr_state == new_state)
+ new_state = common_pwr_sm_run(curr_state);
+
+ if (curr_state != new_state)
+ pwr_sm_set_state(new_state);
+
+ k_msleep(t_wait_ms);
+ }
+}
+
+static inline void create_pwrseq_thread(void)
+{
+ k_thread_create(&pwrseq_thread_data,
+ pwrseq_thread_stack,
+ K_KERNEL_STACK_SIZEOF(pwrseq_thread_stack),
+ (k_thread_entry_t)pwrseq_loop_thread,
+ NULL, NULL, NULL,
+ K_PRIO_COOP(8), 0, K_NO_WAIT);
+
+ k_thread_name_set(&pwrseq_thread_data, "pwrseq_task");
+}
+
+void init_pwr_seq_state(void)
+{
+ init_chipset_pwr_seq_state();
+
+ pwr_sm_set_state(SYS_POWER_STATE_G3S5);
+}
+
+/* Initialize power sequence system state */
+static int pwrseq_init()
+{
+ LOG_ERR("Pwrseq Init\n");
+
+ /* Configure gpio from device tree */
+ pwrseq_gpio_init();
+ LOG_DBG("Done gpio init");
+ /* TODO: Define initial state of power sequence */
+ LOG_DBG("Init pwr seq state");
+ init_pwr_seq_state();
+ /* Create power sequence state handler core function thread */
+ create_pwrseq_thread();
+ return 0;
+}
+
+SYS_INIT(pwrseq_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);