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 
22 
23 OTTF_DEFINE_TEST_CONFIG();
24 
25 /**
26  * Configure the wdog.
27  */
28 static void config_wdog(const dif_aon_timer_t *aon_timer,
29  const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
30  uint64_t bite_time_us) {
31  uint32_t bark_cycles = 0;
32  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_32_from_us(bark_time_us,
33  &bark_cycles));
34  uint32_t bite_cycles = 0;
35  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_32_from_us(bite_time_us,
36  &bite_cycles));
37 
38  LOG_INFO("Wdog will bark after %u us and bite after %u us",
39  (uint32_t)bark_time_us, (uint32_t)bite_time_us);
40 
41  // Set wdog as a reset source.
43  kDifPwrmgrResetRequestSourceTwo,
45 
46  // Setup the wdog bark and bite timeouts.
47  CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(aon_timer, bark_cycles,
48  bite_cycles, false));
49 }
50 
51 /**
52  * Execute the aon timer wdog bite reset test.
53  */
54 static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
55  const dif_pwrmgr_t *pwrmgr, uint32_t bark_time_us) {
56  uint64_t bite_time_us = bark_time_us * 2;
57  config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
58 
59  // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
60  // precaution.
61  uint32_t wait_us =
62  bark_time_us + (uint32_t)udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1,
63  kClockFreqAonHz, NULL);
64 
65  // Wait bark time and check that the bark interrupt requested.
66  busy_spin_micros(wait_us);
67  bool is_pending = false;
68  CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
69  aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
70  CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
71  wait_us);
72 
73  // Wait for the remaining time to the wdog bite.
74  busy_spin_micros(wait_us);
75  // If we arrive here the test must fail.
76  CHECK(false, "Timeout waiting for Wdog bite reset!");
77 }
78 
79 bool test_main(void) {
80  // Initialize pwrmgr.
81  dif_pwrmgr_t pwrmgr;
82  CHECK_DIF_OK(dif_pwrmgr_init(
84 
85  // Initialize rstmgr to check the reset reason.
86  dif_rstmgr_t rstmgr;
87  CHECK_DIF_OK(dif_rstmgr_init(
89 
90  // Initialize aon timer to use the wdog.
91  dif_aon_timer_t aon_timer;
92  CHECK_DIF_OK(dif_aon_timer_init(
94 
95  // Check if there was a HW reset caused by the wdog bite.
97  rst_info = rstmgr_testutils_reason_get();
98  rstmgr_testutils_reason_clear();
99 
100  CHECK(rst_info == kDifRstmgrResetInfoPor ||
101  rst_info == kDifRstmgrResetInfoWatchdog,
102  "Wrong reset reason %02X", rst_info);
103 
104  if (rst_info == kDifRstmgrResetInfoPor) {
105  LOG_INFO("Booting for the first time, setting wdog");
106  // Executing the wdog bite reset test.
107  wdog_bite_test(&aon_timer, &pwrmgr, /*bark_time_us=*/200);
108  } else if (rst_info == kDifRstmgrResetInfoWatchdog) {
109  LOG_INFO("Booting for the second time due to wdog bite reset");
110 
111  return true;
112  }
113  LOG_ERROR("Got unexpected reset info 0x%x", rst_info);
114  return false;
115 }