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  // Initialize rstmgr since this will check some registers.
43  dif_rstmgr_t rstmgr;
44  CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
45 
46  dif_aon_timer_t aon_timer;
47  CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
48 
49  // Assuming the chip hasn't slept yet, wakeup reason should be empty.
50 
51  // Notice we are clearing rstmgr's RESET_INFO, so after the aon wakeup there
52  // is only one bit set.
53  if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true) {
54  LOG_INFO("POR reset");
55 
56  CHECK(UNWRAP(
57  rstmgr_testutils_reset_info_any(&rstmgr, kDifRstmgrResetInfoPor)));
58 
59  // Prepare rstmgr for a reset.
60  CHECK_STATUS_OK(rstmgr_testutils_pre_reset(&rstmgr));
61 
62  CHECK_STATUS_OK(
63  aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold));
64  // Deep sleep.
65  CHECK_STATUS_OK(pwrmgr_testutils_enable_low_power(
66  &pwrmgr, kDifPwrmgrWakeupRequestSourceFive, 0));
67 
68  // Enter low power mode.
69  LOG_INFO("Issue WFI to enter sleep");
71 
72  } else if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(
73  &pwrmgr, kDifPwrmgrWakeupRequestSourceFive)) == true) {
74  LOG_INFO("Wakeup reset");
75 
76  CHECK(UNWRAP(rstmgr_testutils_is_reset_info(
78  LOG_INFO("Aon timer wakeup detected");
79  CHECK_STATUS_OK(rstmgr_testutils_post_reset(
80  &rstmgr, kDifRstmgrResetInfoLowPowerExit, 0, 0, 0, 0));
81 
82  return true;
83  } else {
84  dif_pwrmgr_wakeup_reason_t wakeup_reason;
85  CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason));
86  LOG_ERROR("Unexpected wakeup detected: type = %d, request_source = %d",
87  wakeup_reason.types, wakeup_reason.request_sources);
88  return false;
89  }
90 
91  return false;
92 }