Software APIs
pwrmgr_smoketest.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 
10 #include "sw/device/lib/testing/aon_timer_testutils.h"
11 #include "sw/device/lib/testing/pwrmgr_testutils.h"
12 #include "sw/device/lib/testing/rstmgr_testutils.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
15 
16 static_assert(kDtPwrmgrCount == 1, "this test expects exactly one pwrmgr");
17 static const dt_pwrmgr_t kPwrmgrDt = 0;
18 static_assert(kDtRstmgrCount == 1, "this test expects exactly one rstmgr");
19 static const dt_rstmgr_t kRstmgrDt = 0;
20 static_assert(kDtAonTimerCount >= 1,
21  "this test expects at least one aon_timer");
22 static const dt_aon_timer_t kAonTimerDt = 0;
23 
24 OTTF_DEFINE_TEST_CONFIG();
25 
26 bool test_main(void) {
27  // Issue a wakeup signal in ~150us through the AON timer.
28  //
29  // At 200kHz, threshold of 30 is equal to 150us. There is an additional
30  // ~4 cycle overhead for the CSR value to synchronize with the AON clock.
31  // We should expect the wake up to trigger in ~170us. This is sufficient
32  // time to allow pwrmgr config and the low power entry on WFI to complete.
33  //
34  // Adjust the threshold for Verilator since it runs on different clock
35  // frequencies.
36  uint64_t wakeup_threshold = kDeviceType == kDeviceSimVerilator ? 300 : 30;
37 
38  // Initialize pwrmgr
39  dif_pwrmgr_t pwrmgr;
40  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
41 
42  dif_pwrmgr_request_sources_t wakeup_sources;
43  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
44  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_aon_timer_instance_id(kAonTimerDt),
45  kDtAonTimerWakeupWkupReq, &wakeup_sources));
46 
47  // Initialize rstmgr since this will check some registers.
48  dif_rstmgr_t rstmgr;
49  CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
50 
51  dif_aon_timer_t aon_timer;
52  CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
53 
54  // Assuming the chip hasn't slept yet, wakeup reason should be empty.
55 
56  // Notice we are clearing rstmgr's RESET_INFO, so after the aon wakeup there
57  // is only one bit set.
58  if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true) {
59  LOG_INFO("POR reset");
60 
61  CHECK(UNWRAP(
62  rstmgr_testutils_reset_info_any(&rstmgr, kDifRstmgrResetInfoPor)));
63 
64  // Prepare rstmgr for a reset.
65  CHECK_STATUS_OK(rstmgr_testutils_pre_reset(&rstmgr));
66 
67  CHECK_STATUS_OK(
68  aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold));
69  // Deep sleep.
70  CHECK_STATUS_OK(
71  pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources, 0));
72 
73  // Enter low power mode.
74  LOG_INFO("Issue WFI to enter sleep");
76 
77  } else if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(
78  &pwrmgr, wakeup_sources)) == true) {
79  LOG_INFO("Wakeup reset");
80 
81  CHECK(UNWRAP(rstmgr_testutils_is_reset_info(
83  LOG_INFO("Aon timer wakeup detected");
84  CHECK_STATUS_OK(rstmgr_testutils_post_reset(
85  &rstmgr, kDifRstmgrResetInfoLowPowerExit, 0, 0, 0, 0));
86 
87  return true;
88  } else {
89  dif_pwrmgr_wakeup_reason_t wakeup_reason;
90  CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason));
91  LOG_ERROR("Unexpected wakeup detected: type = %d, request_source = %d",
92  wakeup_reason.types, wakeup_reason.request_sources);
93  return false;
94  }
95 
96  return false;
97 }