Merge "Add pwrmgr reset tests and clean up sw/device/tests/sim_dv/BUILD"
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson
index 164c73a..00a5a91 100644
--- a/hw/top_matcha/dv/chip_sim_cfg.hjson
+++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -1092,7 +1092,7 @@
{
name: chip_sw_pwrmgr_random_sleep_all_reset_reqs
uvm_test_seq: chip_sw_random_sleep_all_reset_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_all_reset_reqs_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_all_reset_reqs_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=50_000_000"]
run_timeout_mins: 120
@@ -1100,7 +1100,7 @@
{
name: chip_sw_pwrmgr_deep_sleep_all_reset_reqs
uvm_test_seq: chip_sw_deep_sleep_all_reset_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_all_reset_reqs_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_all_reset_reqs_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=50_000_000"]
run_timeout_mins: 120
@@ -1108,28 +1108,28 @@
{
name: chip_sw_pwrmgr_normal_sleep_all_reset_reqs
uvm_test_seq: chip_sw_deep_sleep_all_reset_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_normal_sleep_all_reset_reqs_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_normal_sleep_all_reset_reqs_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_timeout_mins: 120
}
{
name: chip_sw_pwrmgr_sleep_power_glitch_reset
uvm_test_seq: chip_sw_main_power_glitch_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_sleep_power_glitch_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_sleep_power_glitch_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+bypass_alert_ready_to_end_check=1"]
}
{
name: chip_sw_pwrmgr_deep_sleep_power_glitch_reset
uvm_test_seq: chip_sw_deep_power_glitch_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_power_glitch_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_power_glitch_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+bypass_alert_ready_to_end_check=1"]
}
{
name: chip_sw_pwrmgr_random_sleep_power_glitch_reset
uvm_test_seq: chip_sw_random_power_glitch_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_power_glitch_reset_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_power_glitch_reset_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+bypass_alert_ready_to_end_check=1",
"+sw_test_timeout_ns=24_000_000"]
@@ -1629,7 +1629,7 @@
{
name: chip_sw_pwrmgr_b2b_sleep_reset_req
uvm_test_seq: chip_sw_repeat_reset_wkup_vseq
- sw_images: ["//sw/device/tests/sim_dv:pwrmgr_b2b_sleep_reset_test:1"]
+ sw_images: ["//sw/device/tests/sim_dv:pwrmgr_b2b_sleep_reset_test:1:matcha"]
en_run_modes: ["sw_test_mode_test_rom"]
run_opts: ["+sw_test_timeout_ns=35_000_000"]
run_timeout_mins: 120
@@ -2081,6 +2081,8 @@
"chip_sw_otbn_smoketest",
"chip_sw_otp_ctrl_escalation",
"chip_sw_otp_ctrl_smoketest",
+ "chip_sw_pwrmgr_deep_sleep_power_glitch_reset",
+ "chip_sw_pwrmgr_sleep_power_glitch_reset",
"chip_sw_rom_ctrl_integrity_check",
"chip_sw_rstmgr_smoketest",
"chip_sw_rstmgr_sw_req",
@@ -2150,6 +2152,13 @@
"chip_sw_otbn_smoketest",
"chip_sw_otp_ctrl_escalation",
"chip_sw_otp_ctrl_smoketest",
+ "chip_sw_pwrmgr_b2b_sleep_reset_req",
+ "chip_sw_pwrmgr_deep_sleep_all_reset_reqs",
+ "chip_sw_pwrmgr_deep_sleep_power_glitch_reset",
+ "chip_sw_pwrmgr_normal_sleep_all_reset_reqs",
+ "chip_sw_pwrmgr_random_sleep_all_reset_reqs",
+ "chip_sw_pwrmgr_random_sleep_power_glitch_reset",
+ "chip_sw_pwrmgr_sleep_power_glitch_reset",
"chip_sw_pwrmgr_sleep_sensor_ctrl_alert_wakeup",
"chip_sw_rom_ctrl_integrity_check",
"chip_sw_rstmgr_smoketest",
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD
index 8740d12..9bec762 100644
--- a/sw/device/tests/sim_dv/BUILD
+++ b/sw/device/tests/sim_dv/BUILD
@@ -8,32 +8,22 @@
matcha_dv_test(
name = "uart_tx_rx_test",
srcs = ["uart_tx_rx_test.c"],
- targets = ["dv"],
deps = [
- "//hw/top_matcha/ip/clkmgr/data/autogen:clkmgr_regs",
- "//hw/top_matcha/ip/pinmux/data/autogen:pinmux_regs",
- "//hw/top_matcha/sw/autogen:top_matcha",
"//sw/device/lib/dif:clkmgr",
+ "//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:rv_plic_sec",
"//sw/device/lib/testing:clkmgr_testutils",
- "//sw/device/lib/testing/test_framework:ottf_main",
+ "//sw/device/tests:test_dv_lib",
"@lowrisc_opentitan//hw/ip/lc_ctrl/data:lc_ctrl_regs",
- "@lowrisc_opentitan//sw/device/lib/base:mmio",
"@lowrisc_opentitan//sw/device/lib/dif:lc_ctrl",
"@lowrisc_opentitan//sw/device/lib/dif:uart",
- "@lowrisc_opentitan//sw/device/lib/runtime:hart",
- "@lowrisc_opentitan//sw/device/lib/runtime:irq",
- "@lowrisc_opentitan//sw/device/lib/runtime:log",
],
)
matcha_dv_test(
name = "rv_dm_ndm_reset_req",
srcs = ["rv_dm_ndm_reset_req.c"],
- targets = ["dv"],
deps = [
- "//hw/top_matcha/ip/pinmux/data/autogen:pinmux_regs",
- "//hw/top_matcha/sw/autogen:top_matcha",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:rstmgr",
"//sw/device/tests:test_dv_lib",
@@ -54,26 +44,87 @@
matcha_dv_test(
name = "i2c_host_tx_rx_test",
srcs = ["i2c_host_tx_rx_test.c"],
- targets = ["dv"],
deps = [
- "//hw/top_matcha/ip/pinmux/data/autogen:pinmux_regs",
"//sw/device/lib/dif:pinmux",
"//sw/device/lib/dif:rstmgr",
+ "//sw/device/lib/testing:isr_testutils",
"//sw/device/tests:test_dv_lib",
"@lowrisc_opentitan//sw/device/lib/dif:i2c",
"@lowrisc_opentitan//sw/device/lib/testing:i2c_testutils",
- "//sw/device/lib/testing:isr_testutils",
"@lowrisc_opentitan//sw/device/lib/testing:rand_testutils",
],
)
+cc_library(
+ name = "pwrmgr_reset_test_lib",
+ deps = [
+ "//sw/device/lib/dif:alert_handler",
+ "//sw/device/lib/dif:pinmux",
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/lib/dif:rv_plic_sec",
+ "//sw/device/lib/testing:pinmux_testutils",
+ "//sw/device/tests:test_dv_lib",
+ "@lowrisc_opentitan//sw/device/lib/base:abs_mmio",
+ "@lowrisc_opentitan//sw/device/lib/dif:aon_timer",
+ "@lowrisc_opentitan//sw/device/lib/dif:flash_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/dif:rv_timer",
+ "@lowrisc_opentitan//sw/device/lib/dif:sysrst_ctrl",
+ "@lowrisc_opentitan//sw/device/lib/testing:alert_handler_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:flash_ctrl_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_random_sleep_all_reset_reqs_test",
+ srcs = ["pwrmgr_random_sleep_all_reset_reqs_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_deep_sleep_all_reset_reqs_test",
+ srcs = ["pwrmgr_deep_sleep_all_reset_reqs_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_normal_sleep_all_reset_reqs_test",
+ srcs = ["pwrmgr_normal_sleep_all_reset_reqs_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_random_sleep_power_glitch_reset_test",
+ srcs = ["pwrmgr_random_sleep_power_glitch_reset_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_b2b_sleep_reset_test",
+ srcs = ["pwrmgr_b2b_sleep_reset_test.c"],
+ deps = [
+ ":pwrmgr_reset_test_lib",
+ ],
+)
+
################################################################################
# Place the Opentitan-sourced DV test below. #
# Opentitan DV binary build flow does not support centOS7, so we pull the #
# source code and build them here using `matcha_dv_test` rule. #
################################################################################
-
matcha_dv_test(
name = "spi_tx_rx_test",
srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:spi_tx_rx_test.c"],
@@ -168,3 +219,27 @@
"@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils",
],
)
+
+matcha_dv_test(
+ name = "pwrmgr_sleep_power_glitch_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:pwrmgr_sleep_power_glitch_test.c"],
+ deps = [
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/tests:test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+ ],
+)
+
+matcha_dv_test(
+ name = "pwrmgr_deep_sleep_power_glitch_test",
+ srcs = ["@lowrisc_opentitan//sw/device/tests/sim_dv:pwrmgr_deep_sleep_power_glitch_test.c"],
+ deps = [
+ "//sw/device/lib/dif:rstmgr",
+ "//sw/device/tests:test_dv_lib_opentitan",
+ "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr",
+ "@lowrisc_opentitan//sw/device/lib/testing:pwrmgr_testutils",
+ "@lowrisc_opentitan//sw/device/lib/testing:rstmgr_testutils",
+ ],
+)
diff --git a/sw/device/tests/sim_dv/pwrmgr_b2b_sleep_reset_test.c b/sw/device/tests/sim_dv/pwrmgr_b2b_sleep_reset_test.c
new file mode 100644
index 0000000..35b3be0
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_b2b_sleep_reset_test.c
@@ -0,0 +1,182 @@
+// Copyright 2023 Google LLC.
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "aon_timer_regs.h"
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+/*
+ PWRMGR BACK TO BACK DEEP SLEEP, RESET / WAKEUP TEST
+
+ This test introduces reset or wakeup event close to (before or after)
+ entering low power state.
+
+ 'kNumRound' is set to 10 by sv sequence (chip_sw_repeat_reset_wkup_vseq.sv)
+
+ For the reset event, the sequence assert power on resest by driving POR_N
+ PAD. For the wake up event, the seqeunce assert power button in by driving
+ IOR13 PAD.
+
+ */
+OTTF_DEFINE_TEST_CONFIG();
+
+static volatile const uint8_t kNumRound;
+
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_sysrst_ctrl_t sysrst_ctrl;
+static dif_pinmux_t pinmux;
+
+/**
+ * sysrst_ctrl config for test #1
+ * . set sysrst_ctrl.KEY_INTR_CTL.pwrb_in_H2L to 1
+ * . use IOR13 as pwrb_in
+ */
+static void prgm_push_button_wakeup() {
+ dif_sysrst_ctrl_input_change_config_t config = {
+ .input_changes = kDifSysrstCtrlInputPowerButtonH2L,
+ .debounce_time_threshold = 1, // 5us
+ };
+ CHECK_DIF_OK(
+ dif_sysrst_ctrl_input_change_detect_configure(&sysrst_ctrl, config));
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn,
+ kTopMatchaPinmuxInselIor13));
+}
+
+bool test_main(void) {
+ // Issue a wakeup signal in ~1.5 ms through the AON timer.
+ // This timer is needed when reset or wakeup fail to
+ // bring state machine back to active state.
+ // This can happen when wake up event comes before low power
+ // entry event.
+ uint32_t wakeup_threshold = kDeviceType == kDeviceSimVerilator ? 3000 : 300;
+
+ // Initialize pwrmgr
+ dif_pwrmgr_t pwrmgr;
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize rstmgr since this will check some registers.
+ dif_rstmgr_t rstmgr;
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize flash_ctrl
+ CHECK_DIF_OK(dif_flash_ctrl_init_state(
+ &flash_ctrl,
+ mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));
+
+ // Initialize sysrst_ctrl
+ CHECK_DIF_OK(dif_sysrst_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
+ &sysrst_ctrl));
+
+ // Initialize pinmux
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+
+ // First check the flash stored value
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ // Read wakeup reason before check
+ dif_pwrmgr_wakeup_reason_t wakeup_reason;
+ CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason));
+ LOG_INFO("wakeup type:%d wakeup reason: 0x%02X", wakeup_reason.types,
+ wakeup_reason.request_sources);
+
+ if (wakeup_reason.types == 0) {
+ // POR reset
+ CHECK(wakeup_reason.request_sources == 0);
+ } else if (wakeup_reason.types == kDifPwrmgrWakeupTypeRequest) {
+ // sysrst_ctrl or aon_timer
+ CHECK(wakeup_reason.request_sources == (kDifPwrmgrWakeupRequestSourceOne |
+ kDifPwrmgrWakeupRequestSourceFive));
+ } else {
+ LOG_ERROR("unexpected wakeup_type: 0x%x", wakeup_reason.types);
+ }
+
+ // Read reset info before check
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+ LOG_INFO("reset info = 0x%02X", rst_info);
+
+ if (rst_info != kDifRstmgrResetInfoPor &&
+ rst_info != kDifRstmgrResetInfoLowPowerExit) {
+ LOG_ERROR("unexpected reset info: 0x%x", rst_info);
+ }
+
+ dif_aon_timer_t aon_timer;
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // Status clean up
+ if (event_idx > 0) {
+ // aon timer clean up
+ CHECK_DIF_OK(dif_aon_timer_wakeup_stop(&aon_timer));
+ // mmio_region_write32(
+ // mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR),
+ // AON_TIMER_WKUP_CAUSE_REG_OFFSET, 0);
+ CHECK_DIF_OK(dif_aon_timer_clear_wakeup_cause(&aon_timer));
+ // sysrst ctrl status clean up
+ CHECK_DIF_OK(dif_sysrst_ctrl_ulp_wakeup_clear_status(&sysrst_ctrl));
+ }
+
+ if (event_idx < kNumRound) {
+ LOG_INFO("Test round %d", event_idx);
+ } else {
+ LOG_INFO("Test finish");
+ return true;
+ }
+
+ // pin mux / sysrst ctrl set up for push button wakeup
+ prgm_push_button_wakeup();
+
+ // Prepare rstmgr for a reset.
+ rstmgr_testutils_pre_reset(&rstmgr);
+
+ // This is mark for sv sequence to prepare to asserting parallel event.
+ LOG_INFO("ready for power down");
+ busy_spin_micros(10);
+ // timer setup in case wake up comes before entering low power mode
+ aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold);
+
+ // Deep sleep.
+ pwrmgr_testutils_enable_low_power(
+ &pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ 0);
+
+ // Enter low power mode.
+ wait_for_interrupt();
+
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_reset_reqs_test.c b/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_reset_reqs_test.c
new file mode 100644
index 0000000..b5f3191
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_reset_reqs_test.c
@@ -0,0 +1,520 @@
+// Copyright 2023 Google LLC.
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+// In dvsim, one run
+// with --waves can take
+// 1.874h | 38.068ms
+// without --waves,
+// 38.072m | 39.484ms
+
+OTTF_DEFINE_TEST_CONFIG();
+static volatile const uint8_t RST_IDX[7] = {0, 1, 2, 3, 4, 5, 6};
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+
+/**
+ * Objects to access the peripherals used in this test via dif API.
+ */
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rv_plic_t plic;
+static dif_alert_handler_t alert_handler;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_sysrst_ctrl_t sysrst_ctrl_aon;
+static dif_rstmgr_t rstmgr;
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ *
+ * Notice these settings are suitable for sim_dv. For other platforms we scale
+ * the resulting cycles by a factor of 10.
+ */
+enum {
+ kWdogBarkMicros = 3 * 100, // 300 us
+ kWdogBiteMicros = 4 * 100, // 400 us
+ kEscalationPhase0Micros = 1 * 100, // 100 us
+ // The cpu value is slightly larger to avoid flakey results.
+ kEscalationPhase0MicrosCpu = kEscalationPhase0Micros + 20, // 120 us
+ kEscalationPhase1Micros = 5 * 100, // 500 us
+ kEscalationPhase2Micros = 50, // 50 us
+};
+
+static_assert(
+ kWdogBarkMicros < kWdogBiteMicros &&
+ kWdogBarkMicros > kEscalationPhase0Micros &&
+ kWdogBarkMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros) &&
+ kWdogBiteMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros),
+ "The wdog bark and bite shall happens during the escalation phase 1");
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+ top_matcha_plic_peripheral_t peripheral;
+ dif_rv_plic_irq_id_t irq_id;
+ uint32_t irq = 0;
+ uint32_t alert = 0;
+
+ CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+ peripheral = (top_matcha_plic_peripheral_t)
+ top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+ if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+ irq =
+ (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+ // Stops escalation process.
+ CHECK_DIF_OK(dif_alert_handler_escalation_clear(&alert_handler,
+ kDifAlertHandlerClassA));
+ CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+
+ CHECK(irq != kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark,
+ "AON Timer Wdog should not bark");
+
+ } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+ irq = (dif_rv_plic_irq_id_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, alert));
+
+ dif_alert_handler_class_state_t state;
+ CHECK_DIF_OK(dif_alert_handler_get_class_state(
+ &alert_handler, kDifAlertHandlerClassA, &state));
+
+ CHECK(state == kDifAlertHandlerClassStatePhase0, "Wrong phase %d", state);
+
+ CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+ }
+
+ // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+ // register.
+ CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+/**
+ * Initialize the peripherals used in this test.
+ */
+void init_peripherals(void) {
+ // Initialize pwrmgr.
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize sysrst_ctrl.
+ CHECK_DIF_OK(dif_sysrst_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
+ &sysrst_ctrl_aon));
+
+ // Initialize rstmgr to check the reset reason.
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize aon timer to use the wdog.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // Initialize flash_ctrl
+ CHECK_DIF_OK(dif_flash_ctrl_init_state(
+ &flash_ctrl,
+ mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));
+
+ // Initialize plic.
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+ rv_plic_testutils_irq_range_enable(
+ &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+ kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+ // Initialize alert handler.
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+}
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+static void alert_handler_config(void) {
+ dif_alert_handler_alert_t alerts[] = {kTopMatchaAlertIdPwrmgrAonFatalFault};
+ dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassA};
+
+ dif_alert_handler_escalation_phase_t esc_phases[] = {
+ {.phase = kDifAlertHandlerClassStatePhase0,
+ .signal = 0,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase1,
+ .signal = 1,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase1Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase2,
+ .signal = 3,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase2Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()}};
+
+ dif_alert_handler_class_config_t class_config[] = {{
+ .auto_lock_accumulation_counter = kDifToggleDisabled,
+ .accumulator_threshold = 0,
+ .irq_deadline_cycles = alert_handler_testutils_get_cycles_from_us(10) *
+ alert_handler_testutils_cycle_rescaling_factor(),
+ .escalation_phases = esc_phases,
+ .escalation_phases_len = ARRAYSIZE(esc_phases),
+ .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+ }};
+
+ dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
+ dif_alert_handler_config_t config = {
+ .alerts = alerts,
+ .alert_classes = alert_classes,
+ .alerts_len = ARRAYSIZE(alerts),
+ .classes = classes,
+ .class_configs = class_config,
+ .classes_len = ARRAYSIZE(class_config),
+ .ping_timeout = 0,
+ };
+
+ alert_handler_testutils_configure_all(&alert_handler, config,
+ kDifToggleEnabled);
+ // Enables alert handler irq.
+ CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+ &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer interrupt test.
+ */
+static void trigger_escalate(dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr) {
+ uint64_t bark_cycles =
+ udiv64_slow(kWdogBarkMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+ uint64_t bite_cycles =
+ udiv64_slow(kWdogBiteMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ CHECK(bite_cycles < UINT32_MAX,
+ "The value %u can't fit into the 32 bits timer counter.", bite_cycles);
+
+ LOG_INFO(
+ "Wdog will bark after %u/%u us/cycles and bite after %u/%u us/cycles",
+ (uint32_t)kWdogBarkMicros, (uint32_t)bark_cycles,
+ (uint32_t)kWdogBiteMicros, (uint32_t)bite_cycles);
+
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+
+ // Trigger the alert handler to escalate.
+ dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
+ CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
+}
+
+/**
+ * Configure the sysrst.
+ */
+static void config_sysrst(const dif_pwrmgr_t *pwrmgr,
+ const dif_sysrst_ctrl_t *sysrst_ctrl_aon) {
+ LOG_INFO("sysrst enabled");
+
+ // Set sysrst as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceOne,
+ kDifToggleEnabled));
+ LOG_INFO("Reset Request SourceOne is set");
+
+ // Configure sysrst key combo
+ // reset pulse : 50 us
+ // detect durration : 50 us
+
+ dif_sysrst_ctrl_key_combo_config_t sysrst_ctrl_key_combo_config = {
+ .keys = kDifSysrstCtrlKeyAll,
+ .detection_time_threshold = 10,
+ .actions = kDifSysrstCtrlKeyComboActionAll,
+ .embedded_controller_reset_duration = 10};
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure(
+ sysrst_ctrl_aon, kDifSysrstCtrlKeyCombo0, sysrst_ctrl_key_combo_config));
+ // Configure sysrst input change
+ // debounce durration : 100 us
+ dif_sysrst_ctrl_input_change_config_t sysrst_ctrl_input_change_config = {
+ .input_changes = kDifSysrstCtrlInputAll, .debounce_time_threshold = 20};
+
+ // Configure pinmux
+ dif_pinmux_t pinmux;
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure(
+ sysrst_ctrl_aon, sysrst_ctrl_input_change_config));
+
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In,
+ kTopMatchaPinmuxInselIor13));
+}
+
+static void low_power_sysrst(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
+ 0);
+ LOG_INFO("Low power set for sysrst");
+
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void timer_on(uint32_t usec) {
+ busy_spin_micros(usec);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for reset!");
+}
+
+/**
+ * Configure the wdog.
+ */
+static void config_wdog(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
+ uint64_t bite_time_us) {
+ uint32_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bark_time_us);
+ uint32_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bite_time_us);
+
+ LOG_INFO("Wdog will bark after %u us and bite after %u us",
+ (uint32_t)bark_time_us, (uint32_t)bite_time_us);
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+ // Set wdog as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer wdog bite reset test.
+ */
+static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+
+ // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
+ // precaution.
+ uint32_t wait_us =
+ bark_time_us +
+ udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1, kClockFreqAonHz, NULL);
+
+ // Wait bark time and check that the bark interrupt requested.
+ busy_spin_micros(wait_us);
+ bool is_pending = false;
+ CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
+ aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
+ CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
+ wait_us);
+
+ // Wait for the remaining time to the wdog bite.
+ busy_spin_micros(wait_us);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for Wdog bite reset!");
+}
+
+/**
+ * Execute the aon timer wdog bite reset during sleep test.
+ */
+static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr,
+ uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+}
+
+static void low_power_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ 0);
+ LOG_INFO("Low power set for watch dog");
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void low_power_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ 0);
+ LOG_INFO("ready for pad por");
+
+ // Enter in low power mode.
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+bool test_main(void) {
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ init_peripherals();
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdAlertHandlerClassa,
+ kTopMatchaPlicIrqIdAlertHandlerClassd);
+
+ alert_handler_config();
+
+ // First check the flash stored value.
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are.
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ LOG_INFO("Test round %d", event_idx);
+ LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
+
+ // Check if there was a HW reset caused by expected cases.
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+
+ CHECK(rst_info == kDifRstmgrResetInfoPor ||
+ rst_info == kDifRstmgrResetInfoSysRstCtrl ||
+ rst_info == kDifRstmgrResetInfoWatchdog ||
+ rst_info == kDifRstmgrResetInfoEscalation ||
+ rst_info == kDifRstmgrResetInfoLowPowerExit ||
+ rst_info == (kDifRstmgrResetInfoSysRstCtrl |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info ==
+ (kDifRstmgrResetInfoPor | kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoEscalation |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == kDifRstmgrResetInfoSw,
+ "Wrong reset reason %02X", rst_info);
+
+ switch (RST_IDX[event_idx]) {
+ case 0:
+ LOG_INFO("Booting and setting deep sleep followed by sysrst");
+ config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
+ low_power_sysrst(&pwrmgr);
+ break;
+ case 1:
+ LOG_INFO("Booting and setting deep sleep followed by hw por");
+ low_power_por(&pwrmgr);
+ break;
+ case 2:
+ LOG_INFO(
+ "Booting and setting deep sleep mode followed for low_power entry "
+ "reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ // actually the same test as deep sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ break;
+ case 3:
+ LOG_INFO(
+ "Booting and setting deep sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+
+ // Assert reeset req
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ break;
+ case 4:
+ LOG_INFO("Booting and setting deep sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ break;
+ case 5:
+ LOG_INFO("Booting and running normal sleep followed by escalation reset");
+ LOG_INFO("Let SV wait timer reset");
+ trigger_escalate(&aon_timer, &pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 6:
+ LOG_INFO("Last Booting");
+ return true;
+ break;
+ default:
+ LOG_INFO("Booting for undefined case");
+ }
+
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_reset_reqs_test.c b/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_reset_reqs_test.c
new file mode 100644
index 0000000..151b9c5
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_reset_reqs_test.c
@@ -0,0 +1,532 @@
+// Copyright 2023 Google LLC.
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+OTTF_DEFINE_TEST_CONFIG();
+static volatile const uint8_t RST_IDX[7] = {0, 1, 2, 3, 4, 5, 6};
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+
+/**
+ * Objects to access the peripherals used in this test via dif API.
+ */
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rv_plic_t plic;
+static dif_alert_handler_t alert_handler;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_sysrst_ctrl_t sysrst_ctrl_aon;
+static dif_rstmgr_t rstmgr;
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ *
+ * Notice these settings are suitable for sim_dv. For other platforms we scale
+ * the resulting cycles by a factor of 10.
+ */
+enum {
+ kWdogBarkMicros = 3 * 100, // 300 us
+ kWdogBiteMicros = 4 * 100, // 400 us
+ kEscalationPhase0Micros = 1 * 100, // 100 us
+ // The cpu value is slightly larger to avoid flakey results.
+ kEscalationPhase0MicrosCpu = kEscalationPhase0Micros + 20, // 120 us
+ kEscalationPhase1Micros = 5 * 100, // 500 us
+ kEscalationPhase2Micros = 50, // 50 us
+};
+
+static_assert(
+ kWdogBarkMicros < kWdogBiteMicros &&
+ kWdogBarkMicros > kEscalationPhase0Micros &&
+ kWdogBarkMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros) &&
+ kWdogBiteMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros),
+ "The wdog bark and bite shall happens during the escalation phase 1");
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+ top_matcha_plic_peripheral_t peripheral;
+ dif_rv_plic_irq_id_t irq_id;
+ uint32_t irq = 0;
+ uint32_t alert = 0;
+
+ CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+ peripheral = (top_matcha_plic_peripheral_t)
+ top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+ if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+ irq =
+ (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+ // Stops escalation process.
+ CHECK_DIF_OK(dif_alert_handler_escalation_clear(&alert_handler,
+ kDifAlertHandlerClassA));
+ CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+
+ CHECK(irq != kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark,
+ "AON Timer Wdog should not bark");
+
+ } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+ irq = (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, alert));
+
+ dif_alert_handler_class_state_t state;
+ CHECK_DIF_OK(dif_alert_handler_get_class_state(
+ &alert_handler, kDifAlertHandlerClassA, &state));
+
+ CHECK(state == kDifAlertHandlerClassStatePhase0, "Wrong phase %d", state);
+
+ CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+ }
+
+ // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+ // register.
+ CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+/**
+ * Initialize the peripherals used in this test.
+ */
+void init_peripherals(void) {
+ // Initialize pwrmgr.
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize sysrst_ctrl.
+ CHECK_DIF_OK(dif_sysrst_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
+ &sysrst_ctrl_aon));
+
+ // Initialize rstmgr to check the reset reason.
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize aon timer to use the wdog.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // Initialize flash_ctrl
+ CHECK_DIF_OK(dif_flash_ctrl_init_state(
+ &flash_ctrl,
+ mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));
+
+ // Initialize plic.
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+ rv_plic_testutils_irq_range_enable(
+ &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+ kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+ // Initialize alert handler.
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+}
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+static void alert_handler_config(void) {
+ dif_alert_handler_alert_t alerts[] = {kTopMatchaAlertIdPwrmgrAonFatalFault};
+ dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassA};
+
+ dif_alert_handler_escalation_phase_t esc_phases[] = {
+ {.phase = kDifAlertHandlerClassStatePhase0,
+ .signal = 0,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase1,
+ .signal = 1,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase1Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase2,
+ .signal = 3,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase2Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()}};
+
+ dif_alert_handler_class_config_t class_config[] = {{
+ .auto_lock_accumulation_counter = kDifToggleDisabled,
+ .accumulator_threshold = 0,
+ .irq_deadline_cycles = alert_handler_testutils_get_cycles_from_us(10) *
+ alert_handler_testutils_cycle_rescaling_factor(),
+ .escalation_phases = esc_phases,
+ .escalation_phases_len = ARRAYSIZE(esc_phases),
+ .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+ }};
+
+ dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
+ dif_alert_handler_config_t config = {
+ .alerts = alerts,
+ .alert_classes = alert_classes,
+ .alerts_len = ARRAYSIZE(alerts),
+ .classes = classes,
+ .class_configs = class_config,
+ .classes_len = ARRAYSIZE(class_config),
+ .ping_timeout = 0,
+ };
+
+ alert_handler_testutils_configure_all(&alert_handler, config,
+ kDifToggleEnabled);
+ // Enables alert handler irq.
+ CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+ &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer interrupt test.
+ */
+static void config_escalate(dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr) {
+ uint64_t bark_cycles =
+ udiv64_slow(kWdogBarkMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+ uint64_t bite_cycles =
+ udiv64_slow(kWdogBiteMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ CHECK(bite_cycles < UINT32_MAX,
+ "The value %u can't fit into the 32 bits timer counter.", bite_cycles);
+
+ LOG_INFO(
+ "Wdog will bark after %u/%u us/cycles and bite after %u/%u us/cycles",
+ (uint32_t)kWdogBarkMicros, (uint32_t)bark_cycles,
+ (uint32_t)kWdogBiteMicros, (uint32_t)bite_cycles);
+
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+
+ // Trigger the alert handler to escalate.
+ dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
+ CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
+}
+
+/**
+ * Configure the sysrst.
+ */
+static void config_sysrst(const dif_pwrmgr_t *pwrmgr,
+ const dif_sysrst_ctrl_t *sysrst_ctrl_aon) {
+ LOG_INFO("sysrst enabled");
+
+ // Set sysrst as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceOne,
+ kDifToggleEnabled));
+ LOG_INFO("Reset Request SourceOne is set");
+
+ // Configure sysrst key combo
+ // reset pulse : 50 us
+ // detect durration : 50 us
+
+ dif_sysrst_ctrl_key_combo_config_t sysrst_ctrl_key_combo_config = {
+ .keys = kDifSysrstCtrlKeyAll,
+ .detection_time_threshold = 10,
+ .actions = kDifSysrstCtrlKeyComboActionAll,
+ .embedded_controller_reset_duration = 10};
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure(
+ sysrst_ctrl_aon, kDifSysrstCtrlKeyCombo0, sysrst_ctrl_key_combo_config));
+ // Configure sysrst input change
+ // debounce durration : 100 us
+ dif_sysrst_ctrl_input_change_config_t sysrst_ctrl_input_change_config = {
+ .input_changes = kDifSysrstCtrlInputAll, .debounce_time_threshold = 20};
+
+ // Configure pinmux
+ dif_pinmux_t pinmux;
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure(
+ sysrst_ctrl_aon, sysrst_ctrl_input_change_config));
+
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In,
+ kTopMatchaPinmuxInselIor13));
+}
+
+static void normal_sleep_sysrst(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
+ config);
+ LOG_INFO("Normal sleep set for sysrst");
+
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void timer_on(uint32_t usec) {
+ busy_spin_micros(usec);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for reset!");
+}
+
+/**
+ * Configure the wdog.
+ */
+static void config_wdog(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
+ uint64_t bite_time_us) {
+ uint32_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bark_time_us);
+ uint32_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bite_time_us);
+
+ LOG_INFO("Wdog will bark after %u us and bite after %u us",
+ (uint32_t)bark_time_us, (uint32_t)bite_time_us);
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+ // Set wdog as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer wdog bite reset test.
+ */
+static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+
+ // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
+ // precaution.
+ uint32_t wait_us =
+ bark_time_us +
+ udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1, kClockFreqAonHz, NULL);
+
+ // Wait bark time and check that the bark interrupt requested.
+ busy_spin_micros(wait_us);
+ bool is_pending = false;
+ CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
+ aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
+ CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
+ wait_us);
+
+ // Wait for the remaining time to the wdog bite.
+ busy_spin_micros(wait_us);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for Wdog bite reset!");
+}
+
+/**
+ * Execute the aon timer wdog bite reset during sleep test.
+ */
+static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr,
+ uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+}
+
+static void normal_sleep_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ config);
+ LOG_INFO("Normal sleep set for watchdog");
+ wait_for_interrupt();
+}
+
+static void normal_sleep_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ config);
+ LOG_INFO("ready for pad por");
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+bool test_main(void) {
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ init_peripherals();
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdAlertHandlerClassa,
+ kTopMatchaPlicIrqIdAlertHandlerClassd);
+
+ alert_handler_config();
+
+ // First check the flash stored value
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ LOG_INFO("Test round %d", event_idx);
+ LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
+
+ // Check if there was a HW reset caused by expected cases
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+
+ CHECK(rst_info == kDifRstmgrResetInfoPor ||
+ rst_info == kDifRstmgrResetInfoSysRstCtrl ||
+ rst_info == kDifRstmgrResetInfoWatchdog ||
+ rst_info == kDifRstmgrResetInfoEscalation ||
+ rst_info == kDifRstmgrResetInfoLowPowerExit ||
+ rst_info == (kDifRstmgrResetInfoSysRstCtrl |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info ==
+ (kDifRstmgrResetInfoPor | kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoEscalation |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == kDifRstmgrResetInfoSw,
+ "Wrong reset reason %02X", rst_info);
+
+ switch (RST_IDX[event_idx]) {
+ case 0:
+ LOG_INFO("Booting and setting normal sleep followed by sysrst");
+ config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
+ normal_sleep_sysrst(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ break;
+ case 1:
+ LOG_INFO("Booting and setting normal sleep followed by hw por");
+ normal_sleep_por(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ break;
+ case 2:
+ LOG_INFO(
+ "Booting and setting normal sleep mode followed for low_power "
+ "entry reset");
+ LOG_INFO("Let SV wait timer reset");
+ // actually the same test as normal sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 3:
+ LOG_INFO(
+ "Booting and setting normal sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+
+ // Assert reeset req
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 4:
+ LOG_INFO("Booting and setting normal sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 5:
+ LOG_INFO("Booting and running normal sleep followed by escalation reset");
+ LOG_INFO("Let SV wait timer reset");
+ config_escalate(&aon_timer, &pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ break;
+ case 6:
+ LOG_INFO("Last Booting");
+ return true;
+ break;
+ default:
+ LOG_INFO("Booting for undefined case");
+ }
+
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_reset_reqs_test.c b/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_reset_reqs_test.c
new file mode 100644
index 0000000..440a84b
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_reset_reqs_test.c
@@ -0,0 +1,617 @@
+// Copyright 2023 Google LLC.
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+OTTF_DEFINE_TEST_CONFIG();
+static volatile const uint8_t RST_IDX[12] = {0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11};
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+
+/**
+ * Objects to access the peripherals used in this test via dif API.
+ */
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rv_plic_t plic;
+static dif_alert_handler_t alert_handler;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_sysrst_ctrl_t sysrst_ctrl_aon;
+static dif_rstmgr_t rstmgr;
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+enum {
+ kWdogBarkMicros = 3 * 100, // 300 us
+ kWdogBiteMicros = 4 * 100, // 400 us
+ kEscalationPhase0Micros = 1 * 100, // 100 us
+ // The cpu value is slightly larger as the busy_spin_micros
+ // routine cycle count comes out slightly smaller due to the
+ // fact that it does not divide by exactly 1M
+ // see sw/device/lib/runtime/hart.c
+ kEscalationPhase0MicrosCpu = kEscalationPhase0Micros + 20, // 120 us
+ kEscalationPhase1Micros = 5 * 100, // 500 us
+ kEscalationPhase2Micros = 50, // 50 us
+};
+
+static_assert(
+ kWdogBarkMicros < kWdogBiteMicros &&
+ kWdogBarkMicros > kEscalationPhase0Micros &&
+ kWdogBarkMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros) &&
+ kWdogBiteMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros),
+ "The wdog bark and bite shall happens during the escalation phase 1");
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+ top_matcha_plic_peripheral_t peripheral;
+ dif_rv_plic_irq_id_t irq_id;
+ uint32_t irq = 0;
+ uint32_t alert = 0;
+
+ CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+ peripheral = (top_matcha_plic_peripheral_t)
+ top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+ if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+ irq =
+ (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+ // Stops escalation process.
+ CHECK_DIF_OK(dif_alert_handler_escalation_clear(&alert_handler,
+ kDifAlertHandlerClassA));
+ CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+
+ CHECK(irq != kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark,
+ "AON Timer Wdog should not bark");
+
+ } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+ irq = (dif_rv_plic_irq_id_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, alert));
+
+ dif_alert_handler_class_state_t state;
+ CHECK_DIF_OK(dif_alert_handler_get_class_state(
+ &alert_handler, kDifAlertHandlerClassA, &state));
+
+ CHECK(state == kDifAlertHandlerClassStatePhase0, "Wrong phase %d", state);
+
+ CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+ }
+
+ // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+ // register.
+ CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+/**
+ * Initialize the peripherals used in this test.
+ */
+void init_peripherals(void) {
+ // Initialize pwrmgr.
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize sysrst_ctrl.
+ CHECK_DIF_OK(dif_sysrst_ctrl_init(
+ mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR),
+ &sysrst_ctrl_aon));
+
+ // Initialize rstmgr to check the reset reason.
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize aon timer to use the wdog.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // Initialize flash_ctrl
+ CHECK_DIF_OK(dif_flash_ctrl_init_state(
+ &flash_ctrl,
+ mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));
+
+ // Initialize plic.
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+ rv_plic_testutils_irq_range_enable(
+ &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+ kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+ // Initialize alert handler.
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+}
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+static void alert_handler_config(void) {
+ dif_alert_handler_alert_t alerts[] = {kTopMatchaAlertIdPwrmgrAonFatalFault};
+ dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassA};
+
+ dif_alert_handler_escalation_phase_t esc_phases[] = {
+ {.phase = kDifAlertHandlerClassStatePhase0,
+ .signal = 0,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase1,
+ .signal = 1,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase1Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase2,
+ .signal = 3,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase2Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()}};
+
+ dif_alert_handler_class_config_t class_config[] = {{
+ .auto_lock_accumulation_counter = kDifToggleDisabled,
+ .accumulator_threshold = 0,
+ .irq_deadline_cycles = alert_handler_testutils_get_cycles_from_us(10) *
+ alert_handler_testutils_cycle_rescaling_factor(),
+ .escalation_phases = esc_phases,
+ .escalation_phases_len = ARRAYSIZE(esc_phases),
+ .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+ }};
+
+ dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
+ dif_alert_handler_config_t config = {
+ .alerts = alerts,
+ .alert_classes = alert_classes,
+ .alerts_len = ARRAYSIZE(alerts),
+ .classes = classes,
+ .class_configs = class_config,
+ .classes_len = ARRAYSIZE(class_config),
+ .ping_timeout = 0,
+ };
+
+ alert_handler_testutils_configure_all(&alert_handler, config,
+ kDifToggleEnabled);
+ // Enables alert handler irq.
+ CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+ &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer interrupt test.
+ */
+static void config_escalate(dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr) {
+ uint64_t bark_cycles =
+ udiv64_slow(kWdogBarkMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+ uint64_t bite_cycles =
+ udiv64_slow(kWdogBiteMicros * kClockFreqAonHz, 1000000, NULL) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ CHECK(bite_cycles < UINT32_MAX,
+ "The value %u can't fit into the 32 bits timer counter.", bite_cycles);
+
+ LOG_INFO(
+ "Wdog will bark after %u/%u us/cycles and bite after %u/%u us/cycles",
+ (uint32_t)kWdogBarkMicros, (uint32_t)bark_cycles,
+ (uint32_t)kWdogBiteMicros, (uint32_t)bite_cycles);
+
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+
+ // Trigger the alert handler to escalate.
+ dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
+ CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
+}
+
+/**
+ * Configure the sysrst.
+ */
+static void config_sysrst(const dif_pwrmgr_t *pwrmgr,
+ const dif_sysrst_ctrl_t *sysrst_ctrl_aon) {
+ LOG_INFO("sysrst enabled");
+
+ // Set sysrst as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceOne,
+ kDifToggleEnabled));
+ LOG_INFO("Reset Request SourceOne is set");
+
+ // Configure sysrst key combo
+ // reset pulse : 50 us
+ // detect durration : 50 us
+
+ dif_sysrst_ctrl_key_combo_config_t sysrst_ctrl_key_combo_config = {
+ .keys = kDifSysrstCtrlKeyAll,
+ .detection_time_threshold = 10,
+ .actions = kDifSysrstCtrlKeyComboActionAll,
+ .embedded_controller_reset_duration = 10};
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure(
+ sysrst_ctrl_aon, kDifSysrstCtrlKeyCombo0, sysrst_ctrl_key_combo_config));
+ // Configure sysrst input change
+ // debounce durration : 100 us
+ dif_sysrst_ctrl_input_change_config_t sysrst_ctrl_input_change_config = {
+ .input_changes = kDifSysrstCtrlInputAll, .debounce_time_threshold = 20};
+
+ // Configure pinmux
+ dif_pinmux_t pinmux;
+ CHECK_DIF_OK(dif_pinmux_init(
+ mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux));
+
+ CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure(
+ sysrst_ctrl_aon, sysrst_ctrl_input_change_config));
+
+ CHECK_DIF_OK(dif_pinmux_input_select(
+ &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In,
+ kTopMatchaPinmuxInselIor13));
+}
+
+static void low_power_sysrst(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
+ 0);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void normal_sleep_sysrst(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceOne,
+ config);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void timer_on(uint32_t usec) {
+ busy_spin_micros(usec);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for reset!");
+}
+
+/**
+ * Configure the wdog.
+ */
+static void config_wdog(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
+ uint64_t bite_time_us) {
+ uint32_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bark_time_us);
+ uint32_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bite_time_us);
+
+ LOG_INFO("Wdog will bark after %u us and bite after %u us",
+ (uint32_t)bark_time_us, (uint32_t)bite_time_us);
+ // Setup the wdog bark and bite timeouts.
+
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+ // Set wdog as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer wdog bite reset test.
+ */
+static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+
+ // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
+ // precaution.
+ uint32_t wait_us =
+ bark_time_us +
+ udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1, kClockFreqAonHz, NULL);
+
+ // Wait bark time and check that the bark interrupt requested.
+ busy_spin_micros(wait_us);
+ bool is_pending = false;
+ CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
+ aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
+ CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
+ wait_us);
+
+ // Wait for the remaining time to the wdog bite.
+ busy_spin_micros(wait_us);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for Wdog bite reset!");
+}
+
+/**
+ * Execute the aon timer wdog bite reset during sleep test.
+ */
+static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr,
+ uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+}
+
+static void low_power_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ 0);
+ LOG_INFO("Low power set for watch dog");
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void normal_sleep_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ config);
+ LOG_INFO("Normal sleep set for watchdog");
+ wait_for_interrupt();
+}
+
+static void low_power_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ 0);
+ // Enter in low power mode.
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void normal_sleep_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ config);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+bool test_main(void) {
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ init_peripherals();
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdAlertHandlerClassa,
+ kTopMatchaPlicIrqIdAlertHandlerClassd);
+
+ alert_handler_config();
+
+ // First check the flash stored value
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ LOG_INFO("Test round %d", event_idx);
+ LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
+
+ // Check if there was a HW reset caused by expected cases
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+
+ CHECK(rst_info == kDifRstmgrResetInfoPor ||
+ rst_info == kDifRstmgrResetInfoSysRstCtrl ||
+ rst_info == kDifRstmgrResetInfoWatchdog ||
+ rst_info == kDifRstmgrResetInfoEscalation ||
+ rst_info == kDifRstmgrResetInfoLowPowerExit ||
+ rst_info == (kDifRstmgrResetInfoSysRstCtrl |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info ==
+ (kDifRstmgrResetInfoPor | kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoEscalation |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == kDifRstmgrResetInfoSw,
+ "Wrong reset reason %02X", rst_info);
+
+ LOG_INFO("New reset event");
+
+ switch (RST_IDX[event_idx] / 2) {
+ case 0:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by sysrst");
+ config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
+ normal_sleep_sysrst(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by sysrst");
+ config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
+ low_power_sysrst(&pwrmgr);
+ }
+ break;
+ case 1:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by hw por");
+ normal_sleep_por(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by hw por");
+ low_power_por(&pwrmgr);
+ }
+ break;
+ case 2:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO(
+ "Booting and setting normal sleep mode followed for low_power "
+ "entry reset");
+ LOG_INFO("Let SV wait timer reset");
+ // actually the same test as normal sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO(
+ "Booting and setting deep sleep mode followed for low_power entry "
+ "reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ // actually the same test as deep sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+
+ case 3:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO(
+ "Booting and setting normal sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO(
+ "Booting and setting deep sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+ case 4:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+ case 5:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Last Booting");
+
+ return true;
+ } else {
+ LOG_INFO(
+ "Booting and running normal sleep followed by escalation reset");
+ config_escalate(&aon_timer, &pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ }
+ break;
+ default:
+ LOG_INFO("Booting for undefined case");
+ }
+ return false;
+}
diff --git a/sw/device/tests/sim_dv/pwrmgr_random_sleep_power_glitch_reset_test.c b/sw/device/tests/sim_dv/pwrmgr_random_sleep_power_glitch_reset_test.c
new file mode 100644
index 0000000..3f16463
--- /dev/null
+++ b/sw/device/tests/sim_dv/pwrmgr_random_sleep_power_glitch_reset_test.c
@@ -0,0 +1,577 @@
+// Copyright 2023 Google LLC.
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#include <assert.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hw/top_matcha/sw/autogen/top_matcha.h"
+#include "sw/device/lib/base/abs_mmio.h"
+#include "sw/device/lib/base/math.h"
+#include "sw/device/lib/base/mmio.h"
+#include "sw/device/lib/dif/dif_alert_handler.h"
+#include "sw/device/lib/dif/dif_aon_timer.h"
+#include "sw/device/lib/dif/dif_flash_ctrl.h"
+#include "sw/device/lib/dif/dif_pinmux.h"
+#include "sw/device/lib/dif/dif_pwrmgr.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
+#include "sw/device/lib/dif/dif_rv_plic.h"
+#include "sw/device/lib/dif/dif_rv_timer.h"
+#include "sw/device/lib/dif/dif_sysrst_ctrl.h"
+#include "sw/device/lib/runtime/irq.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/testing/alert_handler_testutils.h"
+#include "sw/device/lib/testing/aon_timer_testutils.h"
+#include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/pwrmgr_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/rv_plic_testutils.h"
+#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+#include "sw/device/lib/testing/test_framework/ottf_main.h"
+
+OTTF_DEFINE_TEST_CONFIG();
+static volatile const uint8_t RST_IDX[12] = {0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 10, 11};
+static const uint32_t kPlicTarget = kTopMatchaPlicTargetIbex0;
+
+/**
+ * Objects to access the peripherals used in this test via dif API.
+ */
+static dif_flash_ctrl_state_t flash_ctrl;
+static dif_rv_plic_t plic;
+static dif_alert_handler_t alert_handler;
+static dif_aon_timer_t aon_timer;
+static dif_pwrmgr_t pwrmgr;
+static dif_rstmgr_t rstmgr;
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+enum {
+ kWdogBarkMicros = 3 * 100, // 300 us
+ kWdogBiteMicros = 4 * 100, // 400 us
+ kEscalationPhase0Micros = 1 * 100, // 100 us
+ // The cpu value is slightly larger as the busy_spin_micros
+ // routine cycle count comes out slightly smaller due to the
+ // fact that it does not divide by exactly 1M
+ // see sw/device/lib/runtime/hart.c
+ kEscalationPhase0MicrosCpu = kEscalationPhase0Micros + 20, // 120 us
+ kEscalationPhase1Micros = 5 * 100, // 500 us
+ kEscalationPhase2Micros = 50, // 50 us
+};
+
+static_assert(
+ kWdogBarkMicros < kWdogBiteMicros &&
+ kWdogBarkMicros > kEscalationPhase0Micros &&
+ kWdogBarkMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros) &&
+ kWdogBiteMicros < (kEscalationPhase0Micros + kEscalationPhase1Micros),
+ "The wdog bark and bite shall happens during the escalation phase 1");
+
+/**
+ * External ISR.
+ *
+ * Handles all peripheral interrupts on Ibex. PLIC asserts an external interrupt
+ * line to the CPU, which results in a call to this OTTF ISR. This ISR
+ * overrides the default OTTF implementation.
+ */
+void ottf_external_isr(void) {
+ top_matcha_plic_peripheral_t peripheral;
+ dif_rv_plic_irq_id_t irq_id;
+ uint32_t irq = 0;
+ uint32_t alert = 0;
+
+ CHECK_DIF_OK(dif_rv_plic_irq_claim(&plic, kPlicTarget, &irq_id));
+
+ peripheral = (top_matcha_plic_peripheral_t)
+ top_matcha_plic_interrupt_for_peripheral[irq_id];
+
+ if (peripheral == kTopMatchaPlicPeripheralAonTimerAon) {
+ irq =
+ (dif_aon_timer_irq_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired);
+
+ // Stops escalation process.
+ CHECK_DIF_OK(dif_alert_handler_escalation_clear(&alert_handler,
+ kDifAlertHandlerClassA));
+ CHECK_DIF_OK(dif_aon_timer_irq_acknowledge(&aon_timer, irq));
+
+ CHECK(irq != kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark,
+ "AON Timer Wdog should not bark");
+
+ } else if (peripheral == kTopMatchaPlicPeripheralAlertHandler) {
+ irq = (dif_rv_plic_irq_id_t)(irq_id -
+ (dif_rv_plic_irq_id_t)
+ kTopMatchaPlicIrqIdAlertHandlerClassa);
+
+ CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(&alert_handler, alert));
+
+ dif_alert_handler_class_state_t state;
+ CHECK_DIF_OK(dif_alert_handler_get_class_state(
+ &alert_handler, kDifAlertHandlerClassA, &state));
+
+ CHECK(state == kDifAlertHandlerClassStatePhase0, "Wrong phase %d", state);
+
+ CHECK_DIF_OK(dif_alert_handler_irq_acknowledge(&alert_handler, irq));
+ }
+
+ // Complete the IRQ by writing the IRQ source to the Ibex specific CC
+ // register.
+ CHECK_DIF_OK(dif_rv_plic_irq_complete(&plic, kPlicTarget, irq_id));
+}
+
+/**
+ * Initialize the peripherals used in this test.
+ */
+void init_peripherals(void) {
+ // Initialize pwrmgr.
+ CHECK_DIF_OK(dif_pwrmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr));
+
+ // Initialize rstmgr to check the reset reason.
+ CHECK_DIF_OK(dif_rstmgr_init(
+ mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));
+
+ // Initialize aon timer to use the wdog.
+ CHECK_DIF_OK(dif_aon_timer_init(
+ mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer));
+
+ // Initialize flash_ctrl
+ CHECK_DIF_OK(dif_flash_ctrl_init_state(
+ &flash_ctrl,
+ mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));
+
+ // Initialize plic.
+ CHECK_DIF_OK(dif_rv_plic_init(
+ mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &plic));
+
+ rv_plic_testutils_irq_range_enable(
+ &plic, kPlicTarget, kTopMatchaPlicIrqIdAonTimerAonWkupTimerExpired,
+ kTopMatchaPlicIrqIdAonTimerAonWdogTimerBark);
+
+ // Initialize alert handler.
+ CHECK_DIF_OK(dif_alert_handler_init(
+ mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
+ &alert_handler));
+}
+
+/**
+ * Program the alert handler to escalate on alerts upto phase 2 (i.e. reset) but
+ * the phase 1 (i.e. wipe secrets) should occur and last during the time the
+ * wdog is programed to bark.
+ */
+static void alert_handler_config(void) {
+ dif_alert_handler_alert_t alerts[] = {kTopMatchaAlertIdPwrmgrAonFatalFault};
+ dif_alert_handler_class_t alert_classes[] = {kDifAlertHandlerClassA};
+
+ dif_alert_handler_escalation_phase_t esc_phases[] = {
+ {.phase = kDifAlertHandlerClassStatePhase0,
+ .signal = 0,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase1,
+ .signal = 1,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase1Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()},
+ {.phase = kDifAlertHandlerClassStatePhase2,
+ .signal = 3,
+ .duration_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase2Micros) *
+ alert_handler_testutils_cycle_rescaling_factor()}};
+
+ dif_alert_handler_class_config_t class_config[] = {{
+ .auto_lock_accumulation_counter = kDifToggleDisabled,
+ .accumulator_threshold = 0,
+ .irq_deadline_cycles =
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor(),
+ .escalation_phases = esc_phases,
+ .escalation_phases_len = ARRAYSIZE(esc_phases),
+ .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase3,
+ }};
+
+ dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA};
+ dif_alert_handler_config_t config = {
+ .alerts = alerts,
+ .alert_classes = alert_classes,
+ .alerts_len = ARRAYSIZE(alerts),
+ .classes = classes,
+ .class_configs = class_config,
+ .classes_len = ARRAYSIZE(class_config),
+ .ping_timeout = 0,
+ };
+
+ alert_handler_testutils_configure_all(&alert_handler, config,
+ kDifToggleEnabled);
+ // Enables alert handler irq.
+ CHECK_DIF_OK(dif_alert_handler_irq_set_enabled(
+ &alert_handler, kDifAlertHandlerIrqClassa, kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer interrupt test.
+ */
+static void config_escalate(dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr) {
+ uint64_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(kWdogBarkMicros) *
+ alert_handler_testutils_cycle_rescaling_factor();
+ uint64_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(kWdogBiteMicros) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ LOG_INFO(
+ "Wdog will bark after %u/%u us/cycles and bite after %u/%u us/cycles",
+ (uint32_t)kWdogBarkMicros, (uint32_t)bark_cycles,
+ (uint32_t)kWdogBiteMicros, (uint32_t)bite_cycles);
+
+ // Setup the wdog bark and bite timeouts.
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+
+ // Trigger the alert handler to escalate.
+ dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
+ CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
+}
+
+static void low_power_glitch_reset(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceFive,
+ 0);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void normal_sleep_glitch_reset(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into normal (shallow) power
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceFive,
+ config);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+static void timer_on(uint32_t usec) {
+ busy_spin_micros(usec);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for reset!");
+}
+
+/**
+ * Configure the wdog.
+ */
+static void config_wdog(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
+ uint64_t bite_time_us) {
+ uint32_t bark_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bark_time_us);
+ uint32_t bite_cycles =
+ aon_timer_testutils_get_aon_cycles_from_us(bite_time_us);
+
+ LOG_INFO("Wdog will bark after %u us and bite after %u us",
+ (uint32_t)bark_time_us, (uint32_t)bite_time_us);
+ // Setup the wdog bark and bite timeouts.
+
+ aon_timer_testutils_watchdog_config(aon_timer, bark_cycles, bite_cycles,
+ false);
+ // Set wdog as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+}
+
+/**
+ * Execute the aon timer wdog bite reset test.
+ */
+static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+
+ // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
+ // precaution.
+ uint32_t wait_us =
+ bark_time_us +
+ alert_handler_testutils_get_cycles_from_us(kEscalationPhase0Micros) *
+ alert_handler_testutils_cycle_rescaling_factor();
+
+ // Wait bark time and check that the bark interrupt requested.
+ busy_spin_micros(wait_us);
+ bool is_pending = false;
+ CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
+ aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
+ CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
+ wait_us);
+
+ // Wait for the remaining time to the wdog bite.
+ busy_spin_micros(wait_us);
+ // If we arrive here the test must fail.
+ CHECK(false, "Timeout waiting for Wdog bite reset!");
+}
+
+/**
+ * Execute the aon timer wdog bite reset during sleep test.
+ */
+static void sleep_wdog_bite_test(const dif_aon_timer_t *aon_timer,
+ const dif_pwrmgr_t *pwrmgr,
+ uint64_t bark_time_us) {
+ uint64_t bite_time_us = bark_time_us * 2;
+ config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
+}
+
+static void low_power_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ 0);
+ LOG_INFO("Low power set for watch dog");
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void normal_sleep_wdog(const dif_pwrmgr_t *pwrmgr) {
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Enter in low power mode.
+ pwrmgr_testutils_enable_low_power(pwrmgr, kDifPwrmgrWakeupRequestSourceTwo,
+ config);
+ LOG_INFO("Normal sleep set for watchdog");
+ wait_for_interrupt();
+}
+
+static void low_power_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Program the pwrmgr to go to deep sleep state (clocks off).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ 0);
+ // Enter in low power mode.
+ wait_for_interrupt();
+ // If we arrive here the test must fail.
+ CHECK(false, "Fail to enter in low power mode!");
+}
+
+static void normal_sleep_por(const dif_pwrmgr_t *pwrmgr) {
+ // Set por as a reset source.
+ CHECK_DIF_OK(dif_pwrmgr_set_request_sources(pwrmgr, kDifPwrmgrReqTypeReset,
+ kDifPwrmgrResetRequestSourceTwo,
+ kDifToggleEnabled));
+
+ // Place device into low power and immediately wake.
+ dif_pwrmgr_domain_config_t config;
+ config = kDifPwrmgrDomainOptionUsbClockInLowPower |
+ kDifPwrmgrDomainOptionCoreClockInLowPower |
+ kDifPwrmgrDomainOptionIoClockInLowPower |
+ kDifPwrmgrDomainOptionMainPowerInLowPower;
+
+ // Program the pwrmgr to go to swallow sleep state (clocks on).
+ pwrmgr_testutils_enable_low_power(
+ pwrmgr,
+ (kDifPwrmgrWakeupRequestSourceOne | kDifPwrmgrWakeupRequestSourceTwo |
+ kDifPwrmgrWakeupRequestSourceThree | kDifPwrmgrWakeupRequestSourceFour |
+ kDifPwrmgrWakeupRequestSourceFive | kDifPwrmgrWakeupRequestSourceSix),
+ config);
+ // Enter in low power mode.
+ wait_for_interrupt();
+}
+
+bool test_main(void) {
+ // Enable global and external IRQ at Ibex.
+ irq_global_ctrl(true);
+ irq_external_ctrl(true);
+
+ init_peripherals();
+
+ // Enable all the AON interrupts used in this test.
+ rv_plic_testutils_irq_range_enable(&plic, kPlicTarget,
+ kTopMatchaPlicIrqIdAlertHandlerClassa,
+ kTopMatchaPlicIrqIdAlertHandlerClassd);
+
+ alert_handler_config();
+
+ // First check the flash stored value
+ uint32_t event_idx = flash_ctrl_testutils_counter_get(0);
+
+ // Enable flash access
+ flash_ctrl_testutils_default_region_access(&flash_ctrl,
+ /*rd_en*/ true,
+ /*prog_en*/ true,
+ /*erase_en*/ true,
+ /*scramble_en*/ false,
+ /*ecc_en*/ false,
+ /*he_en*/ false);
+
+ // Increment flash counter to know where we are
+ flash_ctrl_testutils_counter_increment(&flash_ctrl, 0);
+
+ LOG_INFO("Test round %d", event_idx);
+ LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
+
+ // Check if there was a HW reset caused by expected cases
+ dif_rstmgr_reset_info_bitfield_t rst_info;
+ rst_info = rstmgr_testutils_reason_get();
+ rstmgr_testutils_reason_clear();
+ LOG_INFO("reset info = %02X", rst_info);
+
+ CHECK(rst_info == kDifRstmgrResetInfoPor ||
+ rst_info == kDifRstmgrResetInfoSysRstCtrl ||
+ rst_info == kDifRstmgrResetInfoWatchdog ||
+ rst_info == kDifRstmgrResetInfoEscalation ||
+ rst_info == kDifRstmgrResetInfoLowPowerExit ||
+ rst_info == (kDifRstmgrResetInfoSysRstCtrl |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoPowerUnstable |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoPowerUnstable |
+ kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoPowerUnstable |
+ kDifRstmgrResetInfoWatchdog) ||
+ rst_info == kDifRstmgrResetInfoPowerUnstable ||
+ rst_info ==
+ (kDifRstmgrResetInfoPor | kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoWatchdog |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == (kDifRstmgrResetInfoEscalation |
+ kDifRstmgrResetInfoLowPowerExit) ||
+ rst_info == kDifRstmgrResetInfoSw,
+ "Wrong reset reason %02X", rst_info);
+
+ switch (RST_IDX[event_idx] / 2) {
+ case 0:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by glitch reset");
+ LOG_INFO("Let SV wait timer reset");
+ normal_sleep_glitch_reset(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by glitch reset");
+ LOG_INFO("Let SV wait timer reset");
+ low_power_glitch_reset(&pwrmgr);
+ }
+ break;
+ case 1:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by hw por");
+ LOG_INFO("Let SV wait timer reset");
+ normal_sleep_por(&pwrmgr);
+ timer_on(kWdogBiteMicros);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by hw por");
+ LOG_INFO("Let SV wait timer reset");
+ low_power_por(&pwrmgr);
+ }
+ break;
+ case 2:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO(
+ "Booting and setting normal sleep mode followed for low_power "
+ "entry reset");
+ LOG_INFO("Let SV wait timer reset");
+ // actually the same test as normal sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO(
+ "Booting and setting deep sleep mode followed for low_power entry "
+ "reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ // actually the same test as deep sleep + watchdog
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+
+ case 3:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO(
+ "Booting and setting normal sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO(
+ "Booting and setting deep sleep followed by watchdog reset "
+ "combined "
+ "with sw_req");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+ LOG_INFO("Device reset from sw");
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+ case 4:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Booting and setting normal sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ normal_sleep_wdog(&pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ } else {
+ LOG_INFO("Booting and setting deep sleep followed by watchdog reset");
+ LOG_INFO("Let SV wait timer reset");
+ // Executing the wdog bite reset during sleep test.
+ rstmgr_testutils_pre_reset(&rstmgr);
+ sleep_wdog_bite_test(&aon_timer, &pwrmgr, 200);
+ low_power_wdog(&pwrmgr);
+ }
+ break;
+ case 5:
+ if (RST_IDX[event_idx] % 2) {
+ LOG_INFO("Last Booting");
+
+ return true;
+ } else {
+ LOG_INFO(
+ "Booting and running normal sleep followed by escalation reset");
+ config_escalate(&aon_timer, &pwrmgr);
+ timer_on(kEscalationPhase0MicrosCpu);
+ }
+ break;
+ default:
+ LOG_INFO("Booting for undefined case");
+ }
+
+ return false;
+}