Add sysrst_ctrl tests to edacloud Change-Id: I8cab45d4a37d1fc9e88e268c11b90e505de126d7
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson index d9cf1d4..6b01b1a 100644 --- a/hw/top_matcha/dv/chip_sim_cfg.hjson +++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -1152,32 +1152,32 @@ { name: chip_sw_sysrst_ctrl_inputs uvm_test_seq: chip_sw_sysrst_ctrl_inputs_vseq - sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_inputs_test:1"] + sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_inputs_test:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] } { name: chip_sw_sysrst_ctrl_in_irq uvm_test_seq: chip_sw_sysrst_ctrl_in_irq_vseq - sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_in_irq_test:1"] + sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_in_irq_test:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] } { name: chip_sw_sysrst_ctrl_ulp_z3_wakeup uvm_test_seq: chip_sw_sysrst_ctrl_ulp_z3_wakeup_vseq - sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_ulp_z3_wakeup_test:1"] + sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_ulp_z3_wakeup_test:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] } { name: chip_sw_sysrst_ctrl_reset uvm_test_seq: chip_sw_sysrst_ctrl_reset_vseq - sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_reset_test:1"] + sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_reset_test:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] run_opts: ["+sw_test_timeout_ns=36_000_000"] } { name: chip_sw_sysrst_ctrl_outputs uvm_test_seq: chip_sw_sysrst_ctrl_outputs_vseq - sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_outputs_test:1"] + sw_images: ["//sw/device/tests/sim_dv:sysrst_ctrl_outputs_test:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] } { @@ -2051,6 +2051,7 @@ "chip_sw_spi_device_tx_rx", "chip_sw_spi_host_tx_rx", "chip_sw_sram_ctrl_smoketest", + "chip_sw_sysrst_ctrl_inputs", "chip_sw_uart_smoketest", "chip_sw_uart_tx_rx", ] @@ -2136,6 +2137,11 @@ "chip_sw_spi_device_tx_rx", "chip_sw_spi_host_tx_rx", "chip_sw_sram_ctrl_smoketest", + "chip_sw_sysrst_ctrl_in_irq", + "chip_sw_sysrst_ctrl_inputs", + "chip_sw_sysrst_ctrl_outputs", + "chip_sw_sysrst_ctrl_reset", + "chip_sw_sysrst_ctrl_ulp_z3_wakeup", "chip_sw_uart_smoketest", "chip_sw_uart_tx_rx", "chip_tap_straps_dev", @@ -2233,6 +2239,11 @@ "chip_sw_spi_host_tx_rx", "chip_sw_sram_ctrl_smoketest", "chip_sw_uart_smoketest", + "chip_sw_sysrst_ctrl_in_irq", + "chip_sw_sysrst_ctrl_inputs", + "chip_sw_sysrst_ctrl_outputs", + "chip_sw_sysrst_ctrl_reset", + "chip_sw_sysrst_ctrl_ulp_z3_wakeup", "chip_sw_uart_tx_rx", "chip_tap_straps_dev", "chip_tap_straps_prod",
diff --git a/hw/top_matcha/dv/env/chip_if.sv b/hw/top_matcha/dv/env/chip_if.sv index a5efa22..1d957a2 100644 --- a/hw/top_matcha/dv/env/chip_if.sv +++ b/hw/top_matcha/dv/env/chip_if.sv
@@ -484,7 +484,7 @@ // Functional (muxed) interface: Pin wake up signal. // TODO: For these tests, use chip_pins_if instead, so that any pin can be configured to wakeup. pins_if #(.Width(1), .PullStrength("Weak")) pinmux_wkup_if( - .pins(mios[top_matcha_pkg::MioPadIob7]) + .pins(mios[top_matcha_pkg::MioPadIod4]) ); // Functional (muxed) interface: UARTs.
diff --git a/hw/top_matcha/dv/env/seq_lib/chip_sw_sysrst_ctrl_ulp_z3_wakeup_vseq.sv b/hw/top_matcha/dv/env/seq_lib/chip_sw_sysrst_ctrl_ulp_z3_wakeup_vseq.sv index 820f1a7..a143161 100644 --- a/hw/top_matcha/dv/env/seq_lib/chip_sw_sysrst_ctrl_ulp_z3_wakeup_vseq.sv +++ b/hw/top_matcha/dv/env/seq_lib/chip_sw_sysrst_ctrl_ulp_z3_wakeup_vseq.sv
@@ -1,3 +1,4 @@ +// 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 @@ -66,7 +67,7 @@ virtual function void check_wakeup_pin(); logic wakeup_result; - // Read PAD_Z3WAKEUP_PATH <-> IOB7 + // Read PAD_Z3WAKEUP_PATH <-> IOD4 wakeup_result = cfg.chip_vif.pinmux_wkup_if.sample_pin(0); `DV_CHECK_EQ_FATAL(wakeup_result, 1'b1); endfunction @@ -84,10 +85,7 @@ virtual task body(); super.body(); - // TODO(lowRISC/opentitan:#13373): Revisit pad assignments. - // pinmux_wkup_vif (at Iob7) is re-used for PinZ3WakeupOut - // due to lack of unused pins. Disable the default drive - // to this pin. + // Disable the default drive on pinmux_wkup_if (Iod4) cfg.chip_vif.pinmux_wkup_if.drive_en_pin(0, 0); write_test_phase(PHASE_INIT);
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD index 621ecc8..c45c6f5 100644 --- a/sw/device/tests/sim_dv/BUILD +++ b/sw/device/tests/sim_dv/BUILD
@@ -255,6 +255,66 @@ ], ) +cc_library( + name = "sysrst_ctrl_test_lib", + deps = [ + "//sw/device/lib/dif:pinmux", + "//sw/device/tests:test_dv_lib", + "@lowrisc_opentitan//sw/device/lib/dif:sysrst_ctrl", + ], +) + +matcha_dv_test( + name = "sysrst_ctrl_inputs_test", + srcs = ["sysrst_ctrl_inputs_test.c"], + deps = [ + ":sysrst_ctrl_test_lib", + ], +) + +matcha_dv_test( + name = "sysrst_ctrl_in_irq_test", + srcs = ["sysrst_ctrl_in_irq_test.c"], + deps = [ + ":sysrst_ctrl_test_lib", + "@lowrisc_opentitan//sw/device/lib/testing:rv_plic_testutils", + ], +) + +matcha_dv_test( + name = "sysrst_ctrl_ulp_z3_wakeup_test", + srcs = ["sysrst_ctrl_ulp_z3_wakeup_test.c"], + deps = [ + ":sysrst_ctrl_test_lib", + "//sw/device/lib/dif:rstmgr", + "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr", + "@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", + ], +) + +matcha_dv_test( + name = "sysrst_ctrl_reset_test", + srcs = ["sysrst_ctrl_reset_test.c"], + deps = [ + ":sysrst_ctrl_test_lib", + "//sw/device/lib/dif:rstmgr", + "@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 = "sysrst_ctrl_outputs_test", + srcs = ["sysrst_ctrl_outputs_test.c"], + deps = [ + ":sysrst_ctrl_test_lib", + "@lowrisc_opentitan//sw/device/lib/testing:flash_ctrl_testutils", + ], +) + ################################################################################ # Place the Opentitan-sourced DV test below. # # Opentitan DV binary build flow does not support centOS7, so we pull the #
diff --git a/sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.c b/sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.c index a452741..c6bd27a 100644 --- a/sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.c +++ b/sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.c
@@ -89,7 +89,7 @@ dif_pinmux_wakeup_config_t detector_cfg = { .signal_filter = kDifToggleDisabled, .pad_type = kDifPinmuxPadKindMio, - .pad_select = kTopMatchaPinmuxInselIob7, + .pad_select = kTopMatchaPinmuxInselIod4, .mode = kDifPinmuxWakeupModePositiveEdge, .counter_threshold = 0 /* Don't need for posedge detection */, };
diff --git a/sw/device/tests/sim_dv/sysrst_ctrl_in_irq_test.c b/sw/device/tests/sim_dv/sysrst_ctrl_in_irq_test.c new file mode 100644 index 0000000..92bb3f2 --- /dev/null +++ b/sw/device/tests/sim_dv/sysrst_ctrl_in_irq_test.c
@@ -0,0 +1,247 @@ +// 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 "hw/top_matcha/sw/autogen/top_matcha.h" +#include "sw/device/lib/base/mmio.h" +#include "sw/device/lib/dif/dif_pinmux.h" +#include "sw/device/lib/dif/dif_rv_plic.h" +#include "sw/device/lib/dif/dif_sysrst_ctrl.h" +#include "sw/device/lib/runtime/ibex.h" +#include "sw/device/lib/runtime/irq.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/rv_plic_testutils.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 dif_sysrst_ctrl_t sysrst_ctrl; +static dif_rv_plic_t plic; + +enum { + kCurrentTestPhaseTimeoutUsec = 20, + kPlicTarget = kTopMatchaPlicTargetIbex0, +}; + +static volatile dif_sysrst_ctrl_irq_t irq; +static volatile top_matcha_plic_peripheral_t peripheral; +dif_rv_plic_irq_id_t irq_id; + +// Test phase written by testbench. +static volatile const uint8_t kCurrentTestPhase = 0; +uint8_t phase = 0; + +enum { + kOutputNumPads = 0x8, + kOutputNunMioPads = 0x6, +}; + +static const dif_pinmux_index_t kPeripheralInputs[] = { + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey1In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey2In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonAcPresent, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonLidOpen, +}; + +static const dif_pinmux_index_t kInputPads[] = { + kTopMatchaPinmuxInselIob3, kTopMatchaPinmuxInselIob6, + kTopMatchaPinmuxInselIob8, kTopMatchaPinmuxInselIor13, + kTopMatchaPinmuxInselIoc7, kTopMatchaPinmuxInselIoc9, +}; + +static const dif_sysrst_ctrl_pin_t kSysrstCtrlInputs[] = { + kDifSysrstCtrlPinKey0In, kDifSysrstCtrlPinKey1In, + kDifSysrstCtrlPinKey2In, kDifSysrstCtrlPinPowerButtonIn, + kDifSysrstCtrlPinAcPowerPresentIn, kDifSysrstCtrlPinLidOpenIn, + kDifSysrstCtrlPinEcResetInOut, kDifSysrstCtrlPinFlashWriteProtectInOut, +}; + +void test_phase_sync() { + test_status_set(kTestStatusInTest); + test_status_set(kTestStatusInWfi); +} + +/** + * Configure for input change detection, sync with DV side, wait for input + * change interrupt, check the interrupt cause and clear it. + */ +void sysrst_ctrl_input_change_detect( + dif_sysrst_ctrl_key_intr_src_t expected_key_intr_src) { + peripheral = UINT32_MAX; + IBEX_SPIN_FOR(phase++ == kCurrentTestPhase, kCurrentTestPhaseTimeoutUsec); + + // Configure for input change. + dif_sysrst_ctrl_input_change_config_t config = { + .input_changes = (dif_sysrst_ctrl_input_change_t)expected_key_intr_src, + .debounce_time_threshold = 1, // 5us + }; + CHECK_DIF_OK( + dif_sysrst_ctrl_input_change_detect_configure(&sysrst_ctrl, config)); + + test_phase_sync(); + + IBEX_SPIN_FOR(phase++ == kCurrentTestPhase, kCurrentTestPhaseTimeoutUsec); + // Check that the interrupt isn't triggered at the first part of the test. + CHECK(peripheral == UINT32_MAX, + "The interrupt is triggered during input glitch."); + test_phase_sync(); + + wait_for_interrupt(); + // Check that the interrupt is triggered at the second part of the test. + CHECK(peripheral == kTopMatchaPlicPeripheralSysrstCtrlAon, + "The interrupt is not triggered during the test."); + CHECK(irq_id == kTopMatchaPlicIrqIdSysrstCtrlAonEventDetected, + "Wrong irq_id"); + + uint32_t causes; + CHECK_DIF_OK( + dif_sysrst_ctrl_input_change_irq_get_causes(&sysrst_ctrl, &causes)); + CHECK(causes == expected_key_intr_src, "Intr cause do not match: %d vs %d!", + causes, (int)expected_key_intr_src); + + CHECK_DIF_OK( + dif_sysrst_ctrl_input_change_irq_clear_causes(&sysrst_ctrl, causes)); + + // Reset configuration for input change. + config.input_changes = 0; + CHECK_DIF_OK( + dif_sysrst_ctrl_input_change_detect_configure(&sysrst_ctrl, config)); +} + +/** + * Configure for key combo change detection, sync with DV side, wait for input + * change interrupt, check the interrupt cause and clear it. + */ +void sysrst_ctrl_key_combo_detect(dif_sysrst_ctrl_key_combo_t key_combo, + uint32_t combo_keys) { + peripheral = UINT32_MAX; + IBEX_SPIN_FOR(phase++ == kCurrentTestPhase, kCurrentTestPhaseTimeoutUsec); + + // Configure for key combo + dif_sysrst_ctrl_key_combo_config_t sysrst_ctrl_key_combo_config = { + .keys = combo_keys, + .detection_time_threshold = 1, + .actions = kDifSysrstCtrlKeyComboActionInterrupt, + .embedded_controller_reset_duration = 1, + }; + CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure( + &sysrst_ctrl, key_combo, sysrst_ctrl_key_combo_config)); + + test_phase_sync(); + + IBEX_SPIN_FOR(phase++ == kCurrentTestPhase, kCurrentTestPhaseTimeoutUsec); + // Check that the interrupt isn't triggered at the first part of the test. + CHECK(peripheral == UINT32_MAX, + "The interrupt is triggered during input glitch."); + test_phase_sync(); + + wait_for_interrupt(); + // Check that the interrupt is triggered at the second part of the test. + CHECK(peripheral == kTopMatchaPlicPeripheralSysrstCtrlAon, + "The interrupt is not triggered during the test."); + CHECK(irq_id == kTopMatchaPlicIrqIdSysrstCtrlAonEventDetected, + "Wrong irq_id"); + + uint32_t causes; + CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_irq_get_causes(&sysrst_ctrl, &causes)); + CHECK(causes == key_combo, "Intr cause do not match: %d vs %d!", causes, + (int)key_combo); + + CHECK_DIF_OK( + dif_sysrst_ctrl_key_combo_irq_clear_causes(&sysrst_ctrl, causes)); + + // Reset configuration for key combo. + sysrst_ctrl_key_combo_config.keys = 0; + CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure( + &sysrst_ctrl, key_combo, sysrst_ctrl_key_combo_config)); +} + +/** + * External interrupt handler. + */ +void ottf_external_isr(void) { + 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 == kTopMatchaPlicPeripheralSysrstCtrlAon) { + irq = + (dif_sysrst_ctrl_irq_t)(irq_id - + (dif_rv_plic_irq_id_t) + kTopMatchaPlicIrqIdSysrstCtrlAonEventDetected); + CHECK_DIF_OK(dif_sysrst_ctrl_irq_acknowledge(&sysrst_ctrl, 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)); +} + +bool test_main(void) { + // Enable global and external IRQ at Ibex. + irq_global_ctrl(true); + irq_external_ctrl(true); + + // Initialize the PLIC. + mmio_region_t plic_base_addr = + mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR); + CHECK_DIF_OK(dif_rv_plic_init(plic_base_addr, &plic)); + + // Enable all the SYSRST CTRL interrupts on PLIC. + rv_plic_testutils_irq_range_enable( + &plic, kPlicTarget, kTopMatchaPlicIrqIdSysrstCtrlAonEventDetected, + kTopMatchaPlicIrqIdSysrstCtrlAonEventDetected); + + // Initialize sysrst ctrl. + CHECK_DIF_OK(dif_sysrst_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR), + &sysrst_ctrl)); + + // Enable sysrst ctrl irq. + dif_toggle_t irq_state = kDifToggleEnabled; + CHECK_DIF_OK(dif_sysrst_ctrl_irq_set_enabled( + &sysrst_ctrl, kDifSysrstCtrlIrqEventDetected, irq_state)); + + // Set input pins. + dif_pinmux_t pinmux; + CHECK_DIF_OK(dif_pinmux_init( + mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux)); + for (int i = 0; i < kOutputNunMioPads; ++i) { + CHECK_DIF_OK( + dif_pinmux_input_select(&pinmux, kPeripheralInputs[i], kInputPads[i])); + } + + // Test 14 different input transition. 7 L2H and 7 H2L input transition. + for (dif_sysrst_ctrl_key_intr_src_t i = + kDifSysrstCtrlKeyIntrStatusInputPowerButtonH2L; + i <= kDifSysrstCtrlKeyIntrStatusInputFlashWriteProtectL2H; i = i << 1) { + sysrst_ctrl_input_change_detect(i); + } + + // Test 4 different combo key intr sources with 2, 3, 4 and 5 combo key + // transition H2L. + uint32_t combo_keys_0 = kDifSysrstCtrlKeyPowerButton | kDifSysrstCtrlKey0; + sysrst_ctrl_key_combo_detect(kDifSysrstCtrlKeyCombo0, combo_keys_0); + + uint32_t combo_keys_1 = + kDifSysrstCtrlKey1 | kDifSysrstCtrlKey2 | kDifSysrstCtrlKeyAcPowerPresent; + sysrst_ctrl_key_combo_detect(kDifSysrstCtrlKeyCombo1, combo_keys_1); + + uint32_t combo_keys_2 = kDifSysrstCtrlKeyPowerButton | kDifSysrstCtrlKey0 | + kDifSysrstCtrlKey2 | kDifSysrstCtrlKeyAcPowerPresent; + sysrst_ctrl_key_combo_detect(kDifSysrstCtrlKeyCombo2, combo_keys_2); + + uint32_t combo_keys_3 = kDifSysrstCtrlKeyPowerButton | kDifSysrstCtrlKey0 | + kDifSysrstCtrlKey1 | kDifSysrstCtrlKey2 | + kDifSysrstCtrlKeyAcPowerPresent; + sysrst_ctrl_key_combo_detect(kDifSysrstCtrlKeyCombo3, combo_keys_3); + + // Last sync with dv side. + test_status_set(kTestStatusInTest); + return true; +}
diff --git a/sw/device/tests/sim_dv/sysrst_ctrl_inputs_test.c b/sw/device/tests/sim_dv/sysrst_ctrl_inputs_test.c new file mode 100644 index 0000000..93a6a10 --- /dev/null +++ b/sw/device/tests/sim_dv/sysrst_ctrl_inputs_test.c
@@ -0,0 +1,88 @@ +// 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 "hw/top_matcha/sw/autogen/top_matcha.h" +#include "sw/device/lib/base/mmio.h" +#include "sw/device/lib/dif/dif_pinmux.h" +#include "sw/device/lib/dif/dif_sysrst_ctrl.h" +#include "sw/device/lib/runtime/ibex.h" +#include "sw/device/lib/runtime/log.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 dif_sysrst_ctrl_t sysrst_ctrl; +const uint32_t kTestPhaseTimeoutUsec = 10; +const uint32_t kNumPhases = 10; + +// Test phase and expected values written by testbench. +static volatile const uint8_t kTestPhase = 0; +static volatile const uint8_t kTestExpected = 0; + +enum { + kOutputNumPads = 0x8, + kOutputNunMioPads = 0x6, +}; + +static const dif_pinmux_index_t kPeripheralInputs[] = { + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey1In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey2In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonAcPresent, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonLidOpen, +}; + +static const dif_pinmux_index_t kInputPads[] = { + kTopMatchaPinmuxInselIob3, kTopMatchaPinmuxInselIob6, + kTopMatchaPinmuxInselIob8, kTopMatchaPinmuxInselIor13, + kTopMatchaPinmuxInselIoc7, kTopMatchaPinmuxInselIoc9, +}; + +static const dif_sysrst_ctrl_pin_t kSysrstCtrlInputs[] = { + kDifSysrstCtrlPinKey0In, kDifSysrstCtrlPinKey1In, + kDifSysrstCtrlPinKey2In, kDifSysrstCtrlPinPowerButtonIn, + kDifSysrstCtrlPinAcPowerPresentIn, kDifSysrstCtrlPinLidOpenIn, + kDifSysrstCtrlPinEcResetInOut, kDifSysrstCtrlPinFlashWriteProtectInOut, +}; + +static uint8_t read_input_pins(void) { + bool input_value; + uint8_t inputs = 0; + for (int i = 0; i < kOutputNumPads; ++i) { + CHECK_DIF_OK(dif_sysrst_ctrl_input_pin_read( + &sysrst_ctrl, kSysrstCtrlInputs[i], &input_value)); + inputs |= input_value << i; + } + return inputs; +} + +bool test_main(void) { + CHECK_DIF_OK(dif_sysrst_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR), + &sysrst_ctrl)); + + dif_pinmux_t pinmux; + CHECK_DIF_OK(dif_pinmux_init( + mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux)); + + for (int i = 0; i < kOutputNunMioPads; ++i) { + CHECK_DIF_OK( + dif_pinmux_input_select(&pinmux, kPeripheralInputs[i], kInputPads[i])); + } + for (int i = 0; i < kNumPhases; ++i) { + IBEX_SPIN_FOR(i == kTestPhase, kTestPhaseTimeoutUsec); + uint8_t input_pins = read_input_pins(); + CHECK(kTestExpected == input_pins); + // Test status set to InTest then Wfi for testbench synchronization, + // an actual WFI instruction is not issued. + test_status_set(kTestStatusInTest); + test_status_set(kTestStatusInWfi); + } + + test_status_set(kTestStatusInTest); + return true; +}
diff --git a/sw/device/tests/sim_dv/sysrst_ctrl_outputs_test.c b/sw/device/tests/sim_dv/sysrst_ctrl_outputs_test.c new file mode 100644 index 0000000..defa174 --- /dev/null +++ b/sw/device/tests/sim_dv/sysrst_ctrl_outputs_test.c
@@ -0,0 +1,179 @@ +// 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 "hw/top_matcha/sw/autogen/top_matcha.h" +#include "sw/device/lib/base/mmio.h" +#include "sw/device/lib/dif/dif_pinmux.h" +#include "sw/device/lib/dif/dif_sysrst_ctrl.h" +#include "sw/device/lib/runtime/ibex.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/flash_ctrl_testutils.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 dif_pinmux_t pinmux; +static dif_sysrst_ctrl_t sysrst_ctrl; +static dif_flash_ctrl_state_t flash; + +const uint32_t kTestPhaseTimeoutUsec = 100; + +enum { + kTestPhaseSetup = 0, + kTestPhaseLoopback = 1, + kTestPhaseOverrideSetup = 2, + kTestPhaseOverrideZeros = 3, + kTestPhaseOverrideOnes = 4, + kTestPhaseOverrideRelease = 5, + kTestPhaseOverrideAndLoopback = 6, + kTestPhaseDone = 7, +}; + +enum { + kAllZero = 0x0, + kAllOne = 0xff, + kLoopbackPartial = 0x5, + kNumMioInputs = 0x4, + kNumMioOutputs = 0x6, + kOutputNumPads = 0x8, +}; + +static const dif_pinmux_index_t kPeripheralInputs[] = { + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey1In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey2In, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn, +}; + +static const dif_pinmux_index_t kInputPads[] = { + kTopMatchaPinmuxInselIob3, + kTopMatchaPinmuxInselIob6, + kTopMatchaPinmuxInselIob8, + kTopMatchaPinmuxInselIor13, +}; + +static const dif_pinmux_index_t kPeripheralOutputs[] = { + kTopMatchaPinmuxOutselSysrstCtrlAonKey0Out, + kTopMatchaPinmuxOutselSysrstCtrlAonKey1Out, + kTopMatchaPinmuxOutselSysrstCtrlAonKey2Out, + kTopMatchaPinmuxOutselSysrstCtrlAonPwrbOut, + kTopMatchaPinmuxOutselSysrstCtrlAonBatDisable, + kTopMatchaPinmuxOutselSysrstCtrlAonZ3Wakeup, +}; + +static const dif_pinmux_index_t kOutputPads[] = { + kTopMatchaPinmuxMioOutIob9, kTopMatchaPinmuxMioOutIor5, + kTopMatchaPinmuxMioOutIor6, kTopMatchaPinmuxMioOutIoc7, + kTopMatchaPinmuxMioOutIoc9, kTopMatchaPinmuxMioOutIod4, +}; + +static const dif_sysrst_ctrl_pin_t kSysrstCtrlOutputs[] = { + kDifSysrstCtrlPinKey0Out, kDifSysrstCtrlPinKey1Out, + kDifSysrstCtrlPinKey2Out, kDifSysrstCtrlPinPowerButtonOut, + kDifSysrstCtrlPinBatteryDisableOut, kDifSysrstCtrlPinZ3WakeupOut, + kDifSysrstCtrlPinEcResetInOut, kDifSysrstCtrlPinFlashWriteProtectInOut, +}; + +// Test phase written by testbench. +static volatile const uint8_t kTestPhase = 0; + +// Sets up the pinmux to assign input and output pads +// to the sysrst_ctrl peripheral as required. +static void pinmux_setup(void) { + for (int i = 0; i < kNumMioInputs; ++i) { + CHECK_DIF_OK( + dif_pinmux_input_select(&pinmux, kPeripheralInputs[i], kInputPads[i])); + } + for (int i = 0; i < kNumMioOutputs; ++i) { + CHECK_DIF_OK(dif_pinmux_output_select(&pinmux, kOutputPads[i], + kPeripheralOutputs[i])); + } +} + +// Waits for the kTestPhase variable to be changed by a backdoor overwrite +// from the testbench in `chip_sw_sysrst_ctrl_ec_rst_l_vseq.sv`. This will +// indicate that the testbench is ready to proceed with the next phase of the +// test. The function `flash_ctrl_testutils_backdoor_wait_update` it's used to +// deal with possible caching that can prevent the software to read the new +// value of `kTestPhase`. +static void sync_with_testbench(void) { + // Set WFI status for testbench synchronization, + // no actual WFI instruction is issued. + test_status_set(kTestStatusInWfi); + test_status_set(kTestStatusInTest); + flash_ctrl_testutils_backdoor_wait_update(&flash, (uintptr_t)&kTestPhase, + kTestPhaseTimeoutUsec); +} + +// Enables the sysrst_ctrl overrides for the output pins. Allows +// both low and high override values. +static void override_setup(uint8_t pins_to_override) { + for (int i = 0; i < kOutputNumPads; ++i) { + if ((pins_to_override >> i) & 0x1) { + CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_set_enabled( + &sysrst_ctrl, kSysrstCtrlOutputs[i], kDifToggleEnabled)); + CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_set_allowed( + &sysrst_ctrl, kSysrstCtrlOutputs[i], true, true)); + } + } +} + +// Disables the overrides. Allows the outputs to pass-through the +// values from the relevant input pins. +static void override_disable(void) { + for (int i = 0; i < kOutputNumPads; ++i) { + CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_set_enabled( + &sysrst_ctrl, kSysrstCtrlOutputs[i], kDifToggleDisabled)); + } +} + +// Sets the values of the output overrides as required. +static void set_output_overrides(uint8_t override_value) { + for (int i = 0; i < kOutputNumPads; ++i) { + CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_set_override( + &sysrst_ctrl, kSysrstCtrlOutputs[i], (override_value >> i) & 0x1)); + } +} + +bool test_main(void) { + CHECK_DIF_OK(dif_pinmux_init( + mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux)); + CHECK_DIF_OK(dif_sysrst_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR), + &sysrst_ctrl)); + flash_ctrl_testutils_backdoor_init(&flash); + + while (kTestPhase < kTestPhaseDone) { + switch (kTestPhase) { + case kTestPhaseSetup: + pinmux_setup(); + break; + case kTestPhaseLoopback: + break; + case kTestPhaseOverrideSetup: + override_setup(kAllOne); + break; + case kTestPhaseOverrideZeros: + set_output_overrides(kAllZero); + break; + case kTestPhaseOverrideOnes: + set_output_overrides(kAllOne); + break; + case kTestPhaseOverrideRelease: + override_disable(); + break; + case kTestPhaseOverrideAndLoopback: + override_setup(kLoopbackPartial); + set_output_overrides(kLoopbackPartial); + break; + default: + LOG_ERROR("Unexpected test phase : %d", kTestPhase); + break; + } + sync_with_testbench(); + } + return true; +}
diff --git a/sw/device/tests/sim_dv/sysrst_ctrl_reset_test.c b/sw/device/tests/sim_dv/sysrst_ctrl_reset_test.c new file mode 100644 index 0000000..5fa723d --- /dev/null +++ b/sw/device/tests/sim_dv/sysrst_ctrl_reset_test.c
@@ -0,0 +1,186 @@ +// 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 "hw/top_matcha/sw/autogen/top_matcha.h" +#include "sw/device/lib/base/mmio.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/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" + +OTTF_DEFINE_TEST_CONFIG(); + +static dif_pwrmgr_t pwrmgr; +static dif_rstmgr_t rstmgr; +static dif_sysrst_ctrl_t sysrst_ctrl; + +enum { + kTestPhaseCheckComboReset = 0, + kTestPhaseCheckDeepSleepWakeup = 1, + kTestPhaseCheckDeepSleepReset = 2, + kTestPhaseFinalCheck = 3, +}; + +// Threshold/Duration values are not specific to a real-world debounce +// scenario so are kept short to avoid excessive simulation time. +// Assuming a 5us aon clock period. +enum { + kDetectionTimeThreshold = 1024, // ~5ms + kEcResetDuration = 512, // ~2.5ms + kDebounceTimeThreshold = 128, // ~0.6ms +}; + +static volatile const uint8_t kTestPhase = 0; + +static void check_combo_reset(void) { + CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure( + &sysrst_ctrl, kDifSysrstCtrlKeyCombo0, + (dif_sysrst_ctrl_key_combo_config_t){ + .actions = kDifSysrstCtrlKeyComboActionEcReset | + kDifSysrstCtrlKeyComboActionSelfReset, + .detection_time_threshold = kDetectionTimeThreshold, + .embedded_controller_reset_duration = kEcResetDuration, + .keys = kDifSysrstCtrlKey0 | kDifSysrstCtrlKey1})); + + CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure( + &sysrst_ctrl, (dif_sysrst_ctrl_input_change_config_t){ + .debounce_time_threshold = kDebounceTimeThreshold, + .input_changes = kDifSysrstCtrlInputKey0H2L | + kDifSysrstCtrlInputKey1H2L})); + CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_configure( + &sysrst_ctrl, kDifSysrstCtrlPinFlashWriteProtectInOut, + (dif_sysrst_ctrl_pin_config_t){.allow_one = true, + .allow_zero = true, + .enabled = kDifToggleEnabled, + .override_value = true})); + // Prepare rstmgr for a reset with sysrst_ctrl (source one). + rstmgr_testutils_pre_reset(&rstmgr); + CHECK_DIF_OK(dif_pwrmgr_set_request_sources(&pwrmgr, kDifPwrmgrReqTypeReset, + kDifPwrmgrResetRequestSourceOne, + kDifToggleEnabled)); + // Issue WFI and wait for reset condition. + test_status_set(kTestStatusInWfi); + wait_for_interrupt(); +} + +static void check_deep_sleep_wakeup(void) { + CHECK_DIF_OK(dif_sysrst_ctrl_ulp_wakeup_configure( + &sysrst_ctrl, (dif_sysrst_ctrl_ulp_wakeup_config_t){ + .ac_power_debounce_time_threshold = 0, + .lid_open_debounce_time_threshold = 0, + .power_button_debounce_time_threshold = 0, + .enabled = kDifToggleEnabled})); + // Setup low power. + // Wakeup source is from sysrst_ctrl (source one). + rstmgr_testutils_pre_reset(&rstmgr); + pwrmgr_testutils_enable_low_power(&pwrmgr, kDifPwrmgrWakeupRequestSourceOne, + 0); + // Issue WFI and wait for reset condition. + test_status_set(kTestStatusInWfi); + wait_for_interrupt(); +} + +static void check_deep_sleep_reset(void) { + CHECK_DIF_OK(dif_sysrst_ctrl_key_combo_detect_configure( + &sysrst_ctrl, kDifSysrstCtrlKeyCombo1, + (dif_sysrst_ctrl_key_combo_config_t){ + .actions = kDifSysrstCtrlKeyComboActionEcReset | + kDifSysrstCtrlKeyComboActionSelfReset, + .detection_time_threshold = kDetectionTimeThreshold, + .embedded_controller_reset_duration = kEcResetDuration, + .keys = kDifSysrstCtrlKey2 | kDifSysrstCtrlKeyPowerButton})); + CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_configure( + &sysrst_ctrl, kDifSysrstCtrlPinFlashWriteProtectInOut, + (dif_sysrst_ctrl_pin_config_t){.allow_one = true, + .allow_zero = true, + .enabled = kDifToggleEnabled, + .override_value = true})); + CHECK_DIF_OK(dif_sysrst_ctrl_input_change_detect_configure( + &sysrst_ctrl, (dif_sysrst_ctrl_input_change_config_t){ + .debounce_time_threshold = kDebounceTimeThreshold, + .input_changes = kDifSysrstCtrlInputKey2H2L | + kDifSysrstCtrlInputPowerButtonH2L})); + // Setup low power. + // Reset source is from sysrst_ctrl (source one). + rstmgr_testutils_pre_reset(&rstmgr); + CHECK_DIF_OK(dif_pwrmgr_set_request_sources(&pwrmgr, kDifPwrmgrReqTypeReset, + kDifPwrmgrResetRequestSourceOne, + kDifToggleEnabled)); + // Enable low power with wakeup source other than + // sysrst_ctrl (e.g. source two) as we don't want + // a wakeup request but instead a reset. + pwrmgr_testutils_enable_low_power(&pwrmgr, kDifPwrmgrWakeupRequestSourceTwo, + 0); + // Issue WFI and wait for reset condition. + test_status_set(kTestStatusInWfi); + wait_for_interrupt(); +} + +bool test_main(void) { + CHECK_DIF_OK(dif_pwrmgr_init( + mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr)); + CHECK_DIF_OK(dif_rstmgr_init( + mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr)); + CHECK_DIF_OK(dif_sysrst_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR), + &sysrst_ctrl)); + + dif_rstmgr_reset_info_bitfield_t rstmgr_reset_info; + rstmgr_reset_info = rstmgr_testutils_reason_get(); + + 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_pinmux_input_select( + &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey0In, + kTopMatchaPinmuxInselIob3)); + CHECK_DIF_OK(dif_pinmux_input_select( + &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey1In, + kTopMatchaPinmuxInselIob6)); + CHECK_DIF_OK(dif_pinmux_input_select( + &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonKey2In, + kTopMatchaPinmuxInselIob8)); + CHECK_DIF_OK(dif_pinmux_input_select( + &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn, + kTopMatchaPinmuxInselIob9)); + CHECK_DIF_OK(dif_pinmux_input_select( + &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonAcPresent, + kTopMatchaPinmuxInselIoc7)); + CHECK_DIF_OK(dif_pinmux_input_select( + &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonLidOpen, + kTopMatchaPinmuxInselIoc9)); + + CHECK_DIF_OK(dif_sysrst_ctrl_output_pin_override_set_enabled( + &sysrst_ctrl, kDifSysrstCtrlPinEcResetInOut, kDifToggleDisabled)); + + switch (kTestPhase) { + case kTestPhaseCheckComboReset: + CHECK(rstmgr_reset_info == kDifRstmgrResetInfoPor); + check_combo_reset(); + break; + case kTestPhaseCheckDeepSleepWakeup: + CHECK(rstmgr_reset_info == kDifRstmgrResetInfoSysRstCtrl); + check_deep_sleep_wakeup(); + break; + case kTestPhaseCheckDeepSleepReset: + CHECK(rstmgr_reset_info == kDifRstmgrResetInfoLowPowerExit); + check_deep_sleep_reset(); + break; + case kTestPhaseFinalCheck: + CHECK(rstmgr_reset_info == + (kDifRstmgrResetInfoSysRstCtrl | kDifRstmgrResetInfoLowPowerExit)); + return true; + break; + default: + LOG_ERROR("Unexpected test phase : %d", kTestPhase); + break; + } + return false; +}
diff --git a/sw/device/tests/sim_dv/sysrst_ctrl_ulp_z3_wakeup_test.c b/sw/device/tests/sim_dv/sysrst_ctrl_ulp_z3_wakeup_test.c new file mode 100644 index 0000000..194e75c --- /dev/null +++ b/sw/device/tests/sim_dv/sysrst_ctrl_ulp_z3_wakeup_test.c
@@ -0,0 +1,184 @@ +// 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 "hw/top_matcha/sw/autogen/top_matcha.h" +#include "sw/device/lib/base/mmio.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/ibex.h" +#include "sw/device/lib/runtime/log.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" + +OTTF_DEFINE_TEST_CONFIG(); + +// This is updated by the sv component of the test +static volatile const uint8_t kTestPhase = 0; + +static dif_pwrmgr_t pwrmgr; +static dif_rstmgr_t rstmgr; +static dif_pinmux_t pinmux; +static dif_sysrst_ctrl_t sysrst_ctrl; +static dif_flash_ctrl_state_t flash; + +enum { + kNumMioInPads = 3, + kNumMioOutPads = 1, + kTestPhaseTimeoutUsec = 500, + // This means 20 aon_clk ticks ~= 20 * 5 us = 100 us + kDebounceTimer = 20, +}; + +enum { + kTestPhaseInit = 0, + kTestPhaseDriveZero = 1, + kTestPhaseWaitNoWakeup = 2, + kTestPhaseGlitchLidOpen = 3, + kTestPhaseWaitWakeup = 4, + kTestPhaseDone = 5, +}; + +static const dif_pinmux_index_t kPeripheralInputs[] = { + kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonAcPresent, + kTopMatchaPinmuxPeripheralInSysrstCtrlAonLidOpen, +}; + +static const dif_pinmux_index_t kInputPads[] = { + kTopMatchaPinmuxInselIor13, + kTopMatchaPinmuxInselIoc7, + kTopMatchaPinmuxInselIoc9, +}; + +static const dif_pinmux_index_t kPeripheralOutputs[] = { + kTopMatchaPinmuxOutselSysrstCtrlAonZ3Wakeup, +}; + +static const dif_pinmux_index_t kOutputPads[] = { + kTopMatchaPinmuxMioOutIod4, +}; + +/** + * Sets up the pinmux to assign input and output pads to the sysrst_ctrl + * peripheral as required. + */ +static void pinmux_setup(void) { + for (int i = 0; i < kNumMioInPads; ++i) { + CHECK_DIF_OK( + dif_pinmux_input_select(&pinmux, kPeripheralInputs[i], kInputPads[i])); + } + + for (int i = 0; i < kNumMioOutPads; ++i) { + CHECK_DIF_OK(dif_pinmux_output_select(&pinmux, kOutputPads[i], + kPeripheralOutputs[i])); + } +} + +/** + * Waits for `kTestPhase` variable to be changed by a backdoor overwrite + * from the testbench in chip_sw_<testname>_vseq.sv. This will indicate that + * the testbench is ready to proceed with the next phase of the test. + */ +static void wait_next_test_phase(void) { + // Set WFI status for testbench synchronization, + // no actual WFI instruction is issued. + test_status_set(kTestStatusInWfi); + test_status_set(kTestStatusInTest); + flash_ctrl_testutils_backdoor_wait_update(&flash, (uintptr_t)&kTestPhase, + kTestPhaseTimeoutUsec); +} + +/** + * Configure *_debounce_ctl and then enable ULP wakeup. + */ +static void configure_wakeup(void) { + dif_sysrst_ctrl_ulp_wakeup_config_t wakeup_config; + + // Keep toggle disabled when writing debounce configuration + wakeup_config.enabled = kDifToggleDisabled; + wakeup_config.ac_power_debounce_time_threshold = kDebounceTimer; + wakeup_config.lid_open_debounce_time_threshold = kDebounceTimer; + wakeup_config.power_button_debounce_time_threshold = kDebounceTimer; + + CHECK_DIF_OK( + dif_sysrst_ctrl_ulp_wakeup_configure(&sysrst_ctrl, wakeup_config)); + + CHECK_DIF_OK( + dif_sysrst_ctrl_ulp_wakeup_set_enabled(&sysrst_ctrl, kDifToggleEnabled)); +} + +static void go_to_sleep(void) { + // Wakeup source is from sysrst_ctrl (source one). + LOG_INFO("Going to sleep."); + test_status_set(kTestStatusInWfi); + rstmgr_testutils_pre_reset(&rstmgr); + pwrmgr_testutils_enable_low_power(&pwrmgr, kDifPwrmgrWakeupRequestSourceOne, + /*pwrmgr_domain_config=*/0); + wait_for_interrupt(); +} + +static bool reset_is_low_power_exit(void) { + dif_rstmgr_reset_info_bitfield_t rst_info = rstmgr_testutils_reason_get(); + rstmgr_testutils_reason_clear(); + return rst_info == kDifRstmgrResetInfoLowPowerExit; +} + +static bool has_wakeup_happened(void) { + bool wakeup_detected; + CHECK_DIF_OK( + dif_sysrst_ctrl_ulp_wakeup_get_status(&sysrst_ctrl, &wakeup_detected)); + return wakeup_detected; +} + +bool test_main(void) { + CHECK_DIF_OK(dif_sysrst_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR), + &sysrst_ctrl)); + CHECK_DIF_OK(dif_pinmux_init( + mmio_region_from_addr(TOP_MATCHA_PINMUX_AON_BASE_ADDR), &pinmux)); + CHECK_DIF_OK(dif_pwrmgr_init( + mmio_region_from_addr(TOP_MATCHA_PWRMGR_AON_BASE_ADDR), &pwrmgr)); + CHECK_DIF_OK(dif_rstmgr_init( + mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr)); + + flash_ctrl_testutils_backdoor_init(&flash); + + while (kTestPhase < kTestPhaseDone) { + switch (kTestPhase) { + case kTestPhaseInit: + pinmux_setup(); + break; + case kTestPhaseDriveZero: + configure_wakeup(); + LOG_INFO("kTestPhaseDriveZero"); + break; + case kTestPhaseWaitNoWakeup: + CHECK(!reset_is_low_power_exit()); + CHECK(!has_wakeup_happened()); + LOG_INFO("kTestPhaseWaitNoWakeup"); + go_to_sleep(); + break; + case kTestPhaseGlitchLidOpen: + LOG_INFO("kTestPhaseGlitchLidOpen"); + break; + case kTestPhaseWaitWakeup: + CHECK(reset_is_low_power_exit()); + CHECK(has_wakeup_happened()); + LOG_INFO("kTestPhaseWaitWakeup"); + break; + default: + LOG_ERROR("Unexpected test phase : %d", kTestPhase); + LOG_INFO("END"); + break; + } + wait_next_test_phase(); + } + return true; +}