Software APIs
pwrmgr_deep_sleep_power_glitch_test.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "dt/dt_aon_timer.h"
10 #include "sw/device/lib/testing/pwrmgr_testutils.h"
11 #include "sw/device/lib/testing/rstmgr_testutils.h"
12 #include "sw/device/lib/testing/test_framework/check.h"
14 
15 static const dt_rstmgr_t kRstmgrDt = 0;
16 static_assert(kDtRstmgrCount == 1, "this test expects a rstmgr");
17 static const dt_pwrmgr_t kPwrmgrDt = 0;
18 static_assert(kDtPwrmgrCount == 1, "this test expects a pwrmgr");
19 static const dt_aon_timer_t kAonTimerDt = 0;
20 static_assert(kDtAonTimerCount == 1, "this test expects an aon_timer");
21 
22 OTTF_DEFINE_TEST_CONFIG();
23 
24 // When the test first runs the rstmgr's `reset_info` CSR should have the POR
25 // bit set, the code clears reset_info and puts the chip in deep sleep. The WFI
26 // causes core_sleeping to rise, and that causes the SV side to glitch the main
27 // power rail, causing a pwrmgr internally generated reset. The next time the
28 // test runs is after the power glitch reset, which is confirmed reading the
29 // `reset_info` CSR.
30 bool test_main(void) {
31  dif_pwrmgr_t pwrmgr;
32  dif_rstmgr_t rstmgr;
33 
34  // Initialize pwrmgr since this will put the chip in deep sleep.
35  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
36 
37  // Initialize rstmgr since this will check some registers.
38  CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
39 
40  // Notice we are clearing rstmgr's RESET_INFO, so after the power glitch there
41  // is only one bit set.
42 
43  if (UNWRAP(rstmgr_testutils_is_reset_info(&rstmgr, kDifRstmgrResetInfoPor))) {
44  LOG_INFO("Powered up for the first time, begin test");
45 
46  CHECK(UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true);
47 
48  CHECK_STATUS_OK(rstmgr_testutils_pre_reset(&rstmgr));
49 
50  // Any wakeup source will do.
51  dif_pwrmgr_request_sources_t wakeup_sources;
52  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
53  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_aon_timer_instance_id(kAonTimerDt),
54  kDtAonTimerWakeupWkupReq, &wakeup_sources));
55  // Configure deep sleep.
56  CHECK_STATUS_OK(
57  pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources, 0));
58 
59  // This causes core_sleeping to rise and triggers the injection of the
60  // power glitch. Enter low power mode.
61  LOG_INFO("Issue WFI to enter sleep");
63  } else {
64  LOG_INFO("Checking reset status.");
65  CHECK_STATUS_OK(rstmgr_testutils_post_reset(
66  &rstmgr,
68  0, 0, 0));
69  LOG_INFO("Reset status indicates a power glitch and a deep sleep wakeup");
70  }
71  return true;
72 }