Software APIs
pwrmgr_wdog_reset_reqs_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 <limits.h>
6 #include <stdbool.h>
7 #include <stdint.h>
8 
15 #include "sw/device/lib/testing/aon_timer_testutils.h"
16 #include "sw/device/lib/testing/pwrmgr_testutils.h"
17 #include "sw/device/lib/testing/rstmgr_testutils.h"
18 #include "sw/device/lib/testing/test_framework/check.h"
20 
21 static_assert(kDtPwrmgrCount == 1, "this test expects exactly one pwrmgr");
22 static const dt_pwrmgr_t kPwrmgrDt = 0;
23 static_assert(kDtRstmgrCount == 1, "this test expects exactly one rstmgr");
24 static const dt_rstmgr_t kRstmgrDt = 0;
25 static_assert(kDtAonTimerCount >= 1,
26  "this test expects at least one aon_timer");
27 static const dt_aon_timer_t kAonTimerDt = 0;
28 
29 OTTF_DEFINE_TEST_CONFIG();
30 
31 /**
32  * Configure the wdog.
33  */
34 static void config_wdog(const dif_aon_timer_t *aon_timer,
35  const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
36  uint64_t bite_time_us) {
37  uint32_t bark_cycles = 0;
38  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_32_from_us(bark_time_us,
39  &bark_cycles));
40  uint32_t bite_cycles = 0;
41  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_32_from_us(bite_time_us,
42  &bite_cycles));
43 
44  LOG_INFO("Wdog will bark after %u us and bite after %u us",
45  (uint32_t)bark_time_us, (uint32_t)bite_time_us);
46 
47  // Set wdog as a reset source.
48  dif_pwrmgr_request_sources_t reset_sources;
49  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
50  pwrmgr, kDifPwrmgrReqTypeReset, dt_aon_timer_instance_id(kAonTimerDt),
51  kDtAonTimerResetReqAonTimer, &reset_sources));
52  CHECK_DIF_OK(dif_pwrmgr_set_request_sources(
53  pwrmgr, kDifPwrmgrReqTypeReset, reset_sources, kDifToggleEnabled));
54 
55  // Setup the wdog bark and bite timeouts.
56  CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(aon_timer, bark_cycles,
57  bite_cycles, false));
58 }
59 
60 /**
61  * Execute the aon timer wdog bite reset test.
62  */
63 static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
64  const dif_pwrmgr_t *pwrmgr, uint32_t bark_time_us) {
65  uint64_t bite_time_us = bark_time_us * 2;
66  config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
67 
68  // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
69  // precaution.
70  uint64_t aon_timer_clock_freq_hz = dt_clock_frequency(
71  dt_aon_timer_clock(kDtAonTimerAon, kDtAonTimerClockAon));
72  uint32_t wait_us =
73  (uint32_t)bark_time_us +
74  (uint32_t)udiv64_slow(5 * 1000000 + aon_timer_clock_freq_hz - 1,
75  aon_timer_clock_freq_hz, NULL);
76 
77  // Wait bark time and check that the bark interrupt requested.
78  busy_spin_micros(wait_us);
79  bool is_pending = false;
80  CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
81  aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
82  CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
83  wait_us);
84 
85  // Wait for the remaining time to the wdog bite.
86  busy_spin_micros(wait_us);
87  // If we arrive here the test must fail.
88  CHECK(false, "Timeout waiting for Wdog bite reset!");
89 }
90 
91 bool test_main(void) {
92  // Initialize pwrmgr.
93  dif_pwrmgr_t pwrmgr;
94  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
95 
96  // Initialize rstmgr to check the reset reason.
97  dif_rstmgr_t rstmgr;
98  CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
99 
100  // Initialize aon timer to use the wdog.
101  dif_aon_timer_t aon_timer;
102  CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
103 
104  // Check if there was a HW reset caused by the wdog bite.
106  rst_info = rstmgr_testutils_reason_get();
107  rstmgr_testutils_reason_clear();
108 
109  CHECK(rst_info == kDifRstmgrResetInfoPor ||
110  rst_info == kDifRstmgrResetInfoWatchdog,
111  "Wrong reset reason %02X", rst_info);
112 
113  if (rst_info == kDifRstmgrResetInfoPor) {
114  LOG_INFO("Booting for the first time, setting wdog");
115  // Executing the wdog bite reset test.
116  wdog_bite_test(&aon_timer, &pwrmgr, /*bark_time_us=*/200);
117  } else if (rst_info == kDifRstmgrResetInfoWatchdog) {
118  LOG_INFO("Booting for the second time due to wdog bite reset");
119 
120  return true;
121  }
122  LOG_ERROR("Got unexpected reset info 0x%x", rst_info);
123  return false;
124 }