Add pwrmgr wakeup tests Change-Id: I5fa6a5797d4ad96ff46581ee9d37f6fea024f48f
diff --git a/hw/top_matcha/dv/chip_sim_cfg.hjson b/hw/top_matcha/dv/chip_sim_cfg.hjson index 5c178f4..7cec294 100644 --- a/hw/top_matcha/dv/chip_sim_cfg.hjson +++ b/hw/top_matcha/dv/chip_sim_cfg.hjson
@@ -1766,20 +1766,20 @@ { name: chip_sw_pwrmgr_normal_sleep_all_wake_ups uvm_test_seq: "chip_sw_pwrmgr_deep_sleep_all_wake_ups_vseq" - sw_images: ["//sw/device/tests/sim_dv:pwrmgr_normal_sleep_all_wake_ups:1"] + sw_images: ["//sw/device/tests/sim_dv:pwrmgr_normal_sleep_all_wake_ups:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] } { name: chip_sw_pwrmgr_deep_sleep_all_wake_ups uvm_test_seq: "chip_sw_pwrmgr_deep_sleep_all_wake_ups_vseq" - sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_all_wake_ups:1"] + sw_images: ["//sw/device/tests/sim_dv:pwrmgr_deep_sleep_all_wake_ups:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] run_opts: ["+sw_test_timeout_ns=18_000_000"] } { name: chip_sw_pwrmgr_random_sleep_all_wake_ups uvm_test_seq: "chip_sw_pwrmgr_deep_sleep_all_wake_ups_vseq" - sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_all_wake_ups:1"] + sw_images: ["//sw/device/tests/sim_dv:pwrmgr_random_sleep_all_wake_ups:1:matcha"] en_run_modes: ["sw_test_mode_test_rom"] run_opts: ["+sw_test_timeout_ns=18_000_000", "+do_random=1"] } @@ -2084,6 +2084,7 @@ "chip_sw_otp_ctrl_escalation", "chip_sw_otp_ctrl_smoketest", "chip_sw_pwrmgr_deep_sleep_power_glitch_reset", + "chip_sw_pwrmgr_normal_sleep_all_wake_ups" "chip_sw_pwrmgr_sleep_power_glitch_reset", "chip_sw_rom_ctrl_integrity_check", "chip_sw_rstmgr_smoketest", @@ -2158,9 +2159,12 @@ "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_all_wake_ups" "chip_sw_pwrmgr_deep_sleep_power_glitch_reset", "chip_sw_pwrmgr_normal_sleep_all_reset_reqs", + "chip_sw_pwrmgr_normal_sleep_all_wake_ups", "chip_sw_pwrmgr_random_sleep_all_reset_reqs", + "chip_sw_pwrmgr_random_sleep_all_wake_ups", "chip_sw_pwrmgr_random_sleep_power_glitch_reset", "chip_sw_pwrmgr_sleep_power_glitch_reset", "chip_sw_pwrmgr_sleep_sensor_ctrl_alert_wakeup",
diff --git a/sw/device/lib/testing/pinmux_testutils.h b/sw/device/lib/testing/pinmux_testutils.h index 657d6f0..6b401b4 100644 --- a/sw/device/lib/testing/pinmux_testutils.h +++ b/sw/device/lib/testing/pinmux_testutils.h
@@ -3,8 +3,8 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 -#ifndef MATCHA_SW_DEVICE_LIB_TESTING_PINMUX_TESTUTILS_H_ -#define MATCHA_SW_DEVICE_LIB_TESTING_PINMUX_TESTUTILS_H_ +#ifndef SW_DEVICE_LIB_TESTING_PINMUX_TESTUTILS_H_ +#define SW_DEVICE_LIB_TESTING_PINMUX_TESTUTILS_H_ #include <stdint.h> @@ -33,4 +33,4 @@ */ uint32_t pinmux_testutils_get_testable_gpios_mask(void); -#endif // MATCHA_SW_DEVICE_LIB_TESTING_PINMUX_TESTUTILS_H_ +#endif // SW_DEVICE_LIB_TESTING_PINMUX_TESTUTILS_H_
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD index 66a73fd..8c516e3 100644 --- a/sw/device/tests/sim_dv/BUILD +++ b/sw/device/tests/sim_dv/BUILD
@@ -135,6 +135,52 @@ ], ) +cc_library( + name = "pwrmgr_sleep_all_wake_ups_impl", + srcs = [ + "pwrmgr_sleep_all_wake_ups_impl.c", + "pwrmgr_sleep_all_wake_ups_impl.h", + ], + deps = [ + "//sw/device/lib/dif:pinmux", + "//sw/device/lib/dif:rv_plic_sec", + "//sw/device/lib/testing:isr_testutils", + "//sw/device/tests:test_dv_lib", + "@lowrisc_opentitan//sw/device/lib/dif:adc_ctrl", + "@lowrisc_opentitan//sw/device/lib/dif:pwrmgr", + "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl", + "@lowrisc_opentitan//sw/device/lib/dif:usbdev", + "@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:rv_plic_testutils", + ], +) + +matcha_dv_test( + name = "pwrmgr_normal_sleep_all_wake_ups", + srcs = ["pwrmgr_normal_sleep_all_wake_ups.c"], + deps = [ + ":pwrmgr_sleep_all_wake_ups_impl", + ], +) + +matcha_dv_test( + name = "pwrmgr_deep_sleep_all_wake_ups", + srcs = ["pwrmgr_deep_sleep_all_wake_ups.c"], + deps = [ + ":pwrmgr_sleep_all_wake_ups_impl", + ], +) + +matcha_dv_test( + name = "pwrmgr_random_sleep_all_wake_ups", + srcs = ["pwrmgr_random_sleep_all_wake_ups.c"], + deps = [ + ":pwrmgr_sleep_all_wake_ups_impl", + ], +) + ################################################################################ # 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_deep_sleep_all_wake_ups.c b/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_wake_ups.c new file mode 100644 index 0000000..4d2c489 --- /dev/null +++ b/sw/device/tests/sim_dv/pwrmgr_deep_sleep_all_wake_ups.c
@@ -0,0 +1,91 @@ +// 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 "pwrmgr_regs.h" +#include "sw/device/lib/dif/dif_flash_ctrl.h" +#include "sw/device/lib/dif/dif_pwrmgr.h" +#include "sw/device/lib/dif/dif_rv_plic.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/aon_timer_testutils.h" +#include "sw/device/lib/testing/autogen/isr_testutils.h" +#include "sw/device/lib/testing/flash_ctrl_testutils.h" +#include "sw/device/lib/testing/pwrmgr_testutils.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" +#include "sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.h" + +/* + PWRMGR DEEP SLEEP ALL WAKE UPS TEST + + This test runs power manager wake up from deep sleep mode by + wake up inputs. + + There are 6 wake up inputs. + 0: sysrst_ctrl + 1: adc_ctrl + 2: pinmux + 3: usb + 4: aon_timer + 5: sensor_ctrl + + #5 is excluded because sensor_ctrl is not in the aon domain. + */ + +OTTF_DEFINE_TEST_CONFIG(); + +/** + * Clean up pwrmgr wakeup reason register for the next round. + */ +static void delay_n_clear(uint32_t delay_in_us) { + busy_spin_micros(delay_in_us); + CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_clear(&pwrmgr)); +} + +bool test_main(void) { + // Enable global and external IRQ at Ibex. + irq_global_ctrl(true); + irq_external_ctrl(true); + + init_units(); + + // Enable all the AON interrupts used in this test. + rv_plic_testutils_irq_range_enable(&rv_plic, kTopMatchaPlicTargetIbex0, + kTopMatchaPlicIrqIdPwrmgrAonWakeup, + kTopMatchaPlicIrqIdPwrmgrAonWakeup); + + // Enable pwrmgr interrupt. + CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled)); + + // Enable access to flash for storing info across resets. + LOG_INFO("Setting default region accesses"); + 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); + + uint32_t wakeup_count = flash_ctrl_testutils_counter_get(0); + + if (pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) { + LOG_INFO("POR reset"); + execute_test(wakeup_count, /*deep_sleep=*/true); + } else { + check_wakeup_reason(wakeup_count); + LOG_INFO("Woke up by source %d", wakeup_count); + cleanup(wakeup_count); + if (wakeup_count == PWRMGR_PARAM_AON_TIMER_AON_WKUP_REQ_IDX) { + return true; + } + flash_ctrl_testutils_counter_increment(&flash_ctrl, 0); + delay_n_clear(4); + execute_test(wakeup_count + 1, /*deep_sleep=*/true); + } + + return false; +}
diff --git a/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_wake_ups.c b/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_wake_ups.c new file mode 100644 index 0000000..7d8aaf9 --- /dev/null +++ b/sw/device/tests/sim_dv/pwrmgr_normal_sleep_all_wake_ups.c
@@ -0,0 +1,68 @@ +// 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 "pwrmgr_regs.h" +#include "sw/device/lib/dif/dif_pwrmgr.h" +#include "sw/device/lib/dif/dif_rv_plic.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/aon_timer_testutils.h" +#include "sw/device/lib/testing/autogen/isr_testutils.h" +#include "sw/device/lib/testing/pwrmgr_testutils.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" +#include "sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.h" + +/* + PWRMGR NORMAL SLEEP ALL WAKE UPS test + + This test runs power manager wake up from deep sleep mode by + wake up inputs. + + There are 6 wake up inputs. + 0: sysrst_ctrl + 1: adc_ctrl + 2: pinmux + 3: usb + 4: aon_timer + 5: sensor_ctrl + + */ + +OTTF_DEFINE_TEST_CONFIG(); + +bool test_main(void) { + // Enable global and external IRQ at Ibex. + irq_global_ctrl(true); + irq_external_ctrl(true); + + init_units(); + + // Enable all the AON interrupts used in this test. + rv_plic_testutils_irq_range_enable(&rv_plic, kTopMatchaPlicTargetIbex0, + kTopMatchaPlicIrqIdPwrmgrAonWakeup, + kTopMatchaPlicIrqIdPwrmgrAonWakeup); + + // Enable pwrmgr interrupt + CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled)); + + if (pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) { + LOG_INFO("POR reset"); + + for (size_t i = 0; i < PWRMGR_PARAM_NUM_WKUPS; ++i) { + LOG_INFO("Test %d begin", i); + execute_test(i, /*deep_sleep=*/false); + check_wakeup_reason(i); + LOG_INFO("Woke up by source %d", i); + cleanup(i); + LOG_INFO("clean up done source %d", i); + } + + return true; + } + + return false; +}
diff --git a/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_wake_ups.c b/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_wake_ups.c new file mode 100644 index 0000000..248fd4d --- /dev/null +++ b/sw/device/tests/sim_dv/pwrmgr_random_sleep_all_wake_ups.c
@@ -0,0 +1,118 @@ +// 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 "pwrmgr_regs.h" +#include "sw/device/lib/dif/dif_flash_ctrl.h" +#include "sw/device/lib/dif/dif_pwrmgr.h" +#include "sw/device/lib/dif/dif_rv_plic.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/aon_timer_testutils.h" +#include "sw/device/lib/testing/autogen/isr_testutils.h" +#include "sw/device/lib/testing/flash_ctrl_testutils.h" +#include "sw/device/lib/testing/pwrmgr_testutils.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" +#include "sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.h" + +/* + PWRMGR RANDOM SLEEP ALL WAKE UPS TEST + + This test runs power manager wake up from normal or deep sleep mode by + wake up inputs. + + There are 6 wake up inputs. + 0: sysrst_ctrl + 1: adc_ctrl + 2: pinmux + 3: usb + 4: aon_timer + 5: sensor_ctrl + + #5 is excluded because sensor_ctrl is not in the aon domain. + + There are 10 cases to be tested. For each wake up this tests the normal and + deep sleep in succession; for example, case 2 is adc_ctrl normal sleep and + case 3 is adc_ctrl deep sleep. + + This is tracked by a flash_ctrl counter, given there are resets involved. + */ + +OTTF_DEFINE_TEST_CONFIG(); + +/** + * Clean up pwrmgr wakeup reason register for the next round. + */ +static void delay_n_clear(uint32_t delay_in_us) { + busy_spin_micros(delay_in_us); + CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_clear(&pwrmgr)); +} + +int get_wakeup_unit(uint32_t count) { return count / 2; } + +bool get_deep_sleep(uint32_t count) { return (count % 2) == 1; } + +bool test_main(void) { + // Enable global and external IRQ at Ibex. + irq_global_ctrl(true); + irq_external_ctrl(true); + + init_units(); + + // Enable all the AON interrupts used in this test. + rv_plic_testutils_irq_range_enable(&rv_plic, kTopMatchaPlicTargetIbex0, + kTopMatchaPlicIrqIdPwrmgrAonWakeup, + kTopMatchaPlicIrqIdPwrmgrAonWakeup); + + // Enable pwrmgr interrupt. + CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled)); + + // Enable access to flash for storing info across resets. + LOG_INFO("Setting default region accesses"); + 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); + + uint32_t wakeup_count = flash_ctrl_testutils_counter_get(0); + int wakeup_unit = get_wakeup_unit(wakeup_count); + bool deep_sleep = get_deep_sleep(wakeup_count); + + if (pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) { + LOG_INFO("POR reset"); + execute_test(wakeup_unit, deep_sleep); + check_wakeup_reason(wakeup_unit); + LOG_INFO("Woke up by source %d", wakeup_unit); + cleanup(wakeup_unit); + flash_ctrl_testutils_counter_increment(&flash_ctrl, 0); + wakeup_count = flash_ctrl_testutils_counter_get(0); + wakeup_unit = get_wakeup_unit(wakeup_count); + deep_sleep = get_deep_sleep(wakeup_count); + delay_n_clear(4); + execute_test(wakeup_unit, deep_sleep); + } else { + for (int i = 0; i < 2; ++i) { + check_wakeup_reason(wakeup_unit); + LOG_INFO("Woke up by source %d", wakeup_unit); + cleanup(wakeup_unit); + if (wakeup_unit == PWRMGR_PARAM_AON_TIMER_AON_WKUP_REQ_IDX && + deep_sleep) { + return true; + } + flash_ctrl_testutils_counter_increment(&flash_ctrl, 0); + wakeup_count = flash_ctrl_testutils_counter_get(0); + wakeup_unit = get_wakeup_unit(wakeup_count); + deep_sleep = get_deep_sleep(wakeup_count); + delay_n_clear(4); + execute_test(wakeup_unit, deep_sleep); + } + } + + return false; +}
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 new file mode 100644 index 0000000..a452741 --- /dev/null +++ b/sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.c
@@ -0,0 +1,292 @@ +// 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 + +// Contains code that is common to deep, normal, and random sleep for +// pwrmgr all_wake_ups test. + +#include "sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.h" + +#include "hw/top_matcha/sw/autogen/top_matcha.h" +#include "pwrmgr_regs.h" +#include "sw/device/lib/dif/dif_adc_ctrl.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_rv_plic.h" +#include "sw/device/lib/dif/dif_sensor_ctrl.h" +#include "sw/device/lib/dif/dif_sysrst_ctrl.h" +#include "sw/device/lib/dif/dif_usbdev.h" +#include "sw/device/lib/testing/autogen/isr_testutils.h" + +static const uint32_t kPinmuxWkupDetector5 = 5; + +dif_adc_ctrl_t adc_ctrl; +dif_aon_timer_t aon_timer; +dif_flash_ctrl_state_t flash_ctrl; +dif_pinmux_t pinmux; +dif_pwrmgr_t pwrmgr; +dif_rv_plic_t rv_plic; +dif_sensor_ctrl_t sensor_ctrl; +dif_sysrst_ctrl_t sysrst_ctrl; +dif_usbdev_t usbdev; + +/** + * 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_sysrst_ctrl_wakeup(void *dif) { + 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(dif, config)); + CHECK_DIF_OK(dif_pinmux_input_select( + &pinmux, kTopMatchaPinmuxPeripheralInSysrstCtrlAonPwrbIn, + kTopMatchaPinmuxInselIor13)); +} + +/** + * adc_ctrl config for test #2 + * . enable filter 5 and set voltage range (0,200) + */ +static void prgm_adc_ctrl_wakeup(void *dif) { + dif_adc_ctrl_config_t cfg = { + .mode = kDifAdcCtrlLowPowerScanMode, + .power_up_time_aon_cycles = 6, + .wake_up_time_aon_cycles = 100, + .num_low_power_samples = 2, + .num_normal_power_samples = 8, + }; + CHECK_DIF_OK(dif_adc_ctrl_configure(dif, cfg)); + + dif_adc_ctrl_filter_config_t filter_cfg = { + .filter = kDifAdcCtrlFilter5, + .min_voltage = 0, + .max_voltage = 200, + .in_range = true, + .generate_wakeup_on_match = true, + .generate_irq_on_match = false, + }; + + CHECK_DIF_OK(dif_adc_ctrl_configure_filter(dif, kDifAdcCtrlChannel0, + filter_cfg, kDifToggleEnabled)); + CHECK_DIF_OK(dif_adc_ctrl_configure_filter(dif, kDifAdcCtrlChannel1, + filter_cfg, kDifToggleEnabled)); + CHECK_DIF_OK(dif_adc_ctrl_filter_match_wakeup_set_enabled( + dif, kDifAdcCtrlFilter5, kDifToggleEnabled)); + CHECK_DIF_OK(dif_adc_ctrl_set_enabled(dif, kDifToggleEnabled)); +} + +/** + * pinmux config for test #3 + * . use IOB7 as an input + * . set posedge detection + */ +static void prgm_pinmux_wakeup(void *dif) { + dif_pinmux_wakeup_config_t detector_cfg = { + .signal_filter = kDifToggleDisabled, + .pad_type = kDifPinmuxPadKindMio, + .pad_select = kTopMatchaPinmuxInselIob7, + .mode = kDifPinmuxWakeupModePositiveEdge, + .counter_threshold = 0 /* Don't need for posedge detection */, + }; + CHECK_DIF_OK(dif_pinmux_wakeup_detector_enable(dif, kPinmuxWkupDetector5, + detector_cfg)); +} + +/** + * usb config for test #4 + * . Fake low power entry through usb + * . Force usb to output suspend indication + * (*dif) handle is not used but leave as is + * to be called from execute_test + */ +static void prgm_usb_wakeup(void *dif) { + dif_usbdev_phy_pins_drive_t pins = { + .dp_pullup_en = true, + .dn_pullup_en = false, + }; + CHECK_DIF_OK(dif_usbdev_set_phy_pins_state(dif, kDifToggleEnabled, pins)); + CHECK_DIF_OK(dif_usbdev_set_wake_enable(dif, kDifToggleEnabled)); + + LOG_INFO("prgm_usb_wakeup: wait 20us (usb)"); + // Give the hardware a chance to recognize the wakeup values are the same. + busy_spin_micros(20); // 20us +} + +/** + * aon timer config for test #5 + * set wakeup signal in 50us + */ +static void prgm_aontimer_wakeup(void *dif) { + aon_timer_testutils_wakeup_config(dif, 10); +} + +/** + * sensor ctrl config for test #6 + * setup event trigger0 + */ +static void prgm_sensor_ctrl_wakeup(void *dif) { + CHECK_DIF_OK( + dif_sensor_ctrl_set_ast_event_trigger(dif, 0, kDifToggleEnabled)); +} + +const test_wakeup_sources_t kTestWakeupSources[PWRMGR_PARAM_NUM_WKUPS] = { + { + .name = "SYSRST_CTRL", + .dif_handle = &sysrst_ctrl, + .wakeup_src = kDifPwrmgrWakeupRequestSourceOne, + .config = prgm_sysrst_ctrl_wakeup, + }, + { + .name = "ADC_CTRL", + .dif_handle = &adc_ctrl, + .wakeup_src = kDifPwrmgrWakeupRequestSourceTwo, + .config = prgm_adc_ctrl_wakeup, + }, + { + .name = "PINMUX", + .dif_handle = &pinmux, + .wakeup_src = kDifPwrmgrWakeupRequestSourceThree, + .config = prgm_pinmux_wakeup, + }, + { + .name = "USB", + .dif_handle = &usbdev, + .wakeup_src = kDifPwrmgrWakeupRequestSourceFour, + .config = prgm_usb_wakeup, + }, + { + .name = "AONTIMER", + .dif_handle = &aon_timer, + .wakeup_src = kDifPwrmgrWakeupRequestSourceFive, + .config = prgm_aontimer_wakeup, + }, + { + .name = "SENSOR_CTRL", + .dif_handle = &sensor_ctrl, + .wakeup_src = kDifPwrmgrWakeupRequestSourceSix, + .config = prgm_sensor_ctrl_wakeup, + }, +}; + +void init_units() { + CHECK_DIF_OK(dif_adc_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_ADC_CTRL_AON_BASE_ADDR), &adc_ctrl)); + CHECK_DIF_OK(dif_aon_timer_init( + mmio_region_from_addr(TOP_MATCHA_AON_TIMER_AON_BASE_ADDR), &aon_timer)); + CHECK_DIF_OK(dif_flash_ctrl_init_state( + &flash_ctrl, + mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR))); + 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_rv_plic_init( + mmio_region_from_addr(TOP_MATCHA_RV_PLIC_BASE_ADDR), &rv_plic)); + CHECK_DIF_OK(dif_sysrst_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_SYSRST_CTRL_AON_BASE_ADDR), + &sysrst_ctrl)); + CHECK_DIF_OK(dif_sensor_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_SENSOR_CTRL_BASE_ADDR), &sensor_ctrl)); + CHECK_DIF_OK(dif_usbdev_init( + mmio_region_from_addr(TOP_MATCHA_USBDEV_BASE_ADDR), &usbdev)); +} + +void execute_test(uint32_t wakeup_source, bool deep_sleep) { + // Configure wakeup device + kTestWakeupSources[wakeup_source].config( + kTestWakeupSources[wakeup_source].dif_handle); + dif_pwrmgr_domain_config_t cfg; + CHECK_DIF_OK(dif_pwrmgr_get_domain_config(&pwrmgr, &cfg)); + cfg = cfg & (kDifPwrmgrDomainOptionIoClockInLowPower | + kDifPwrmgrDomainOptionUsbClockInLowPower | + kDifPwrmgrDomainOptionUsbClockInActivePower) | + (!deep_sleep ? kDifPwrmgrDomainOptionMainPowerInLowPower : 0); + + pwrmgr_testutils_enable_low_power( + &pwrmgr, kTestWakeupSources[wakeup_source].wakeup_src, cfg); + LOG_INFO("Issue WFI to enter sleep %d", wakeup_source); + wait_for_interrupt(); +} + +void check_wakeup_reason(uint32_t wakeup_source) { + dif_pwrmgr_wakeup_reason_t wakeup_reason; + CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason)); + CHECK(pwrmgr_testutils_is_wakeup_reason( + &pwrmgr, kTestWakeupSources[wakeup_source].wakeup_src) == true, + "wakeup reason wrong exp:%d obs:%d", + kTestWakeupSources[wakeup_source].wakeup_src, wakeup_reason); +} + +static bool get_wakeup_status(void) { + dif_pwrmgr_request_sources_t wake_req = -1; + CHECK_DIF_OK(dif_pwrmgr_get_current_request_sources( + &pwrmgr, kDifPwrmgrReqTypeWakeup, &wake_req)); + return (wake_req > 0); +} + +/** + * Clean up wakeup sources. + */ +void cleanup(uint32_t test_idx) { + switch (test_idx) { + case PWRMGR_PARAM_SYSRST_CTRL_AON_WKUP_REQ_IDX: + CHECK_DIF_OK(dif_sysrst_ctrl_ulp_wakeup_clear_status(&sysrst_ctrl)); + break; + case PWRMGR_PARAM_ADC_CTRL_AON_WKUP_REQ_IDX: + CHECK_DIF_OK(dif_adc_ctrl_filter_match_wakeup_set_enabled( + &adc_ctrl, kDifAdcCtrlFilter5, kDifToggleDisabled)); + break; + case PWRMGR_PARAM_PINMUX_AON_PIN_WKUP_REQ_IDX: + CHECK_DIF_OK(dif_pinmux_wakeup_cause_clear(&pinmux)); + break; + case PWRMGR_PARAM_PINMUX_AON_USB_WKUP_REQ_IDX: + CHECK_DIF_OK(dif_usbdev_set_wake_enable(&usbdev, kDifToggleDisabled)); + CHECK_DIF_OK(dif_pinmux_wakeup_cause_clear(&pinmux)); + break; + case PWRMGR_PARAM_AON_TIMER_AON_WKUP_REQ_IDX: + CHECK_DIF_OK(dif_aon_timer_wakeup_stop(&aon_timer)); + CHECK_DIF_OK(dif_aon_timer_clear_wakeup_cause(&aon_timer)); + break; + case PWRMGR_PARAM_SENSOR_CTRL_WKUP_REQ_IDX: + // clear event trigger + CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, 0, + kDifToggleDisabled)); + CHECK_DIF_OK(dif_sensor_ctrl_clear_recov_event(&sensor_ctrl, 0)); + break; + default: + LOG_ERROR("unknown test index %d", test_idx); + } + + // Ensure the de-asserted events have cleared from the wakeup pipeline + // within 30us. + IBEX_SPIN_FOR(!get_wakeup_status(), 100); + CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_clear(&pwrmgr)); +} +static plic_isr_ctx_t plic_ctx = {.rv_plic = &rv_plic, + .hart_id = kTopMatchaPlicTargetIbex0}; + +static pwrmgr_isr_ctx_t pwrmgr_isr_ctx = { + .pwrmgr = &pwrmgr, + .plic_pwrmgr_start_irq_id = kTopMatchaPlicIrqIdPwrmgrAonWakeup, + .expected_irq = kDifPwrmgrIrqWakeup, + .is_only_irq = true}; + +/** + * External interrupt handler. + */ +void ottf_external_isr(void) { + dif_pwrmgr_irq_t irq_id; + top_matcha_plic_peripheral_t peripheral; + + isr_testutils_pwrmgr_isr(plic_ctx, pwrmgr_isr_ctx, &peripheral, &irq_id); + + // Check that both the peripheral and the irq id is correct + CHECK(peripheral == kTopMatchaPlicPeripheralPwrmgrAon, + "IRQ peripheral: %d is incorrect", peripheral); + CHECK(irq_id == kDifPwrmgrIrqWakeup, "IRQ ID: %d is incorrect", irq_id); +}
diff --git a/sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.h b/sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.h new file mode 100644 index 0000000..9712c3e --- /dev/null +++ b/sw/device/tests/sim_dv/pwrmgr_sleep_all_wake_ups_impl.h
@@ -0,0 +1,68 @@ +// 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 + +#ifndef SW_DEVICE_TESTS_SIM_DV_PWRMGR_SLEEP_ALL_WAKE_UPS_IMPL_H_ +#define SW_DEVICE_TESTS_SIM_DV_PWRMGR_SLEEP_ALL_WAKE_UPS_IMPL_H_ + +// Contains header for code that is common to deep, normal, and random sleep for +// pwrmgr all_wake_ups test. + +#include "sw/device/lib/base/mmio.h" +#include "sw/device/lib/dif/dif_adc_ctrl.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_rv_plic.h" +#include "sw/device/lib/dif/dif_sensor_ctrl.h" +#include "sw/device/lib/dif/dif_sysrst_ctrl.h" +#include "sw/device/lib/dif/dif_usbdev.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/aon_timer_testutils.h" +#include "sw/device/lib/testing/pwrmgr_testutils.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" + +typedef struct test_wakeup_sources { + /** + * Name of the device. + */ + const char *name; + /** + * Handle to the DIF object for this device. + */ + void *dif_handle; + /** + * Wakeup Sources. + */ + dif_pwrmgr_request_sources_t wakeup_src; + /** + * Configuration and initialization actions for the device. + * This will be passed the value of `dif` above. + */ + void (*config)(void *dif); +} test_wakeup_sources_t; + +extern dif_adc_ctrl_t adc_ctrl; +extern dif_aon_timer_t aon_timer; +extern dif_flash_ctrl_state_t flash_ctrl; +extern dif_pinmux_t pinmux; +extern dif_pwrmgr_t pwrmgr; +extern dif_rv_plic_t rv_plic; +extern dif_sensor_ctrl_t sensor_ctrl; +extern dif_sysrst_ctrl_t sysrst_ctrl; +extern dif_usbdev_t usbdev; + +void init_units(); + +void check_wakeup_reason(uint32_t wakeup_source); + +void execute_test(uint32_t wakeup_source, bool deep_sleep); + +void cleanup(uint32_t test_idx); + +#endif // SW_DEVICE_TESTS_SIM_DV_PWRMGR_SLEEP_ALL_WAKE_UPS_IMPL_H_