Software APIs
pwrmgr_sysrst_ctrl_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 
19 #include "sw/device/lib/testing/aon_timer_testutils.h"
20 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
21 #include "sw/device/lib/testing/nv_counter_testutils.h"
22 #include "sw/device/lib/testing/pwrmgr_testutils.h"
23 #include "sw/device/lib/testing/rstmgr_testutils.h"
24 #include "sw/device/lib/testing/test_framework/check.h"
26 
28 
29 OTTF_DEFINE_TEST_CONFIG();
30 static volatile const uint8_t RST_IDX[5] = {3, 30, 130, 5, 50};
31 static dif_flash_ctrl_state_t flash_ctrl;
32 
33 /**
34  * Configure the sysrst.
35  */
36 static void config_sysrst(const dif_pwrmgr_t *pwrmgr,
37  const dif_sysrst_ctrl_t *sysrst_ctrl_aon) {
38  LOG_INFO("sysrst enabled");
39 
40  // Set sysrst as a reset source.
42  kDifPwrmgrResetRequestSourceOne,
44  LOG_INFO("Reset Request SourceOne is set");
45 
46  // Configure sysrst key combo
47  // reset pulse : 50 us
48  // detect duration : 50 us
49 
50  dif_sysrst_ctrl_key_combo_config_t sysrst_ctrl_key_combo_config = {
52  .detection_time_threshold = 10,
54  .embedded_controller_reset_duration = 10};
55 
57  sysrst_ctrl_aon, kDifSysrstCtrlKeyCombo0, sysrst_ctrl_key_combo_config));
58  // Configure sysrst input change
59  // debounce duration : 100 us
60  dif_sysrst_ctrl_input_change_config_t sysrst_ctrl_input_change_config = {
61  .input_changes = kDifSysrstCtrlInputAll, .debounce_time_threshold = 20};
62 
63  // Configure pinmux
64  dif_pinmux_t pinmux;
65  CHECK_DIF_OK(dif_pinmux_init(
67 
69  sysrst_ctrl_aon, sysrst_ctrl_input_change_config));
70 
71  CHECK_DIF_OK(dif_pinmux_input_select(
74 
75  // Wait for sysrst.
76  busy_spin_micros(10 * 1000);
77  // If we arrive here the test must fail.
78  CHECK(false, "Timeout waiting for sysrst reset!");
79 }
80 
81 /**
82  * Configure the wdog.
83  */
84 static void config_wdog(const dif_aon_timer_t *aon_timer,
85  const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us,
86  uint64_t bite_time_us) {
87  uint32_t bark_cycles = 0;
88  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_32_from_us(bark_time_us,
89  &bark_cycles));
90  uint32_t bite_cycles = 0;
91  CHECK_STATUS_OK(aon_timer_testutils_get_aon_cycles_32_from_us(bite_time_us,
92  &bite_cycles));
93 
94  LOG_INFO("Wdog will bark after %u us and bite after %u us",
95  (uint32_t)bark_time_us, (uint32_t)bite_time_us);
96 
97  // Set wdog as a reset source.
99  kDifPwrmgrResetRequestSourceTwo,
101 
102  // Setup the wdog bark and bite timeouts.
103  CHECK_STATUS_OK(aon_timer_testutils_watchdog_config(aon_timer, bark_cycles,
104  bite_cycles, false));
105 }
106 
107 /**
108  * Execute the aon timer wdog bite reset test.
109  */
110 static void wdog_bite_test(const dif_aon_timer_t *aon_timer,
111  const dif_pwrmgr_t *pwrmgr, uint64_t bark_time_us) {
112  uint64_t bite_time_us = bark_time_us * 2;
113  config_wdog(aon_timer, pwrmgr, bark_time_us, bite_time_us);
114 
115  // The `intr_state` takes 3 aon clock cycles to rise plus 2 extra cycles as a
116  // precaution.
117  uint64_t wait_us_u64 =
118  bark_time_us +
119  udiv64_slow(5 * 1000000 + kClockFreqAonHz - 1, kClockFreqAonHz, NULL);
120  CHECK(wait_us_u64 <= UINT32_MAX, "wait_us_u64 must fit in uint32_t");
121  uint32_t wait_us = (uint32_t)wait_us_u64;
122 
123  // Wait bark time and check that the bark interrupt requested.
124  busy_spin_micros(wait_us);
125  bool is_pending = false;
126  CHECK_DIF_OK(dif_aon_timer_irq_is_pending(
127  aon_timer, kDifAonTimerIrqWdogTimerBark, &is_pending));
128  CHECK(is_pending, "Wdog bark irq did not rise after %u microseconds",
129  wait_us);
130 
131  // Wait for the remaining time to the wdog bite.
132  busy_spin_micros(wait_us);
133  // If we arrive here the test must fail.
134  CHECK(false, "Timeout waiting for Wdog bite reset!");
135 }
136 
137 bool test_main(void) {
138  // Initialize pwrmgr.
139  dif_pwrmgr_t pwrmgr;
140  CHECK_DIF_OK(dif_pwrmgr_init(
142 
143  // Initialize sysrst_ctrl.
144  dif_sysrst_ctrl_t sysrst_ctrl_aon;
145  CHECK_DIF_OK(dif_sysrst_ctrl_init(
147  &sysrst_ctrl_aon));
148 
149  // Initialize rstmgr to check the reset reason.
150  dif_rstmgr_t rstmgr;
151  CHECK_DIF_OK(dif_rstmgr_init(
153 
154  // Initialize aon timer to use the wdog.
155  dif_aon_timer_t aon_timer;
156  CHECK_DIF_OK(dif_aon_timer_init(
158 
159  // Initialize flash_ctrl
160  CHECK_DIF_OK(dif_flash_ctrl_init_state(
161  &flash_ctrl,
163 
164  // Enable flash access
165  CHECK_STATUS_OK(
166  flash_ctrl_testutils_default_region_access(&flash_ctrl,
167  /*rd_en*/ true,
168  /*prog_en*/ true,
169  /*erase_en*/ true,
170  /*scramble_en*/ false,
171  /*ecc_en*/ false,
172  /*he_en*/ false));
173 
174  // First check the flash stored value
175  uint32_t event_idx = 0;
176  CHECK_STATUS_OK(flash_ctrl_testutils_counter_get(0, &event_idx));
177 
178  // Increment flash counter to know where we are
179  CHECK_STATUS_OK(flash_ctrl_testutils_counter_increment(&flash_ctrl, 0));
180 
181  LOG_INFO("Test round %d", event_idx);
182  LOG_INFO("RST_IDX[%d] = %d", event_idx, RST_IDX[event_idx]);
183 
184  // Check if there was a HW reset caused by the wdog bite.
186  rst_info = rstmgr_testutils_reason_get();
187  rstmgr_testutils_reason_clear();
188 
189  CHECK(rst_info == kDifRstmgrResetInfoPor ||
190  rst_info == kDifRstmgrResetInfoWatchdog ||
191  rst_info == kDifRstmgrResetInfoSysRstCtrl,
192  "Wrong reset reason %02X", rst_info);
193 
194  if (rst_info == kDifRstmgrResetInfoPor) {
195  LOG_INFO("Booting for the first time, setting sysrst");
196  config_sysrst(&pwrmgr, &sysrst_ctrl_aon);
197  } else if (rst_info == kDifRstmgrResetInfoSysRstCtrl) {
198  LOG_INFO("Booting for the second time due to system reset control reset");
199  // Executing the wdog bite reset test.
200  wdog_bite_test(&aon_timer, &pwrmgr, /*bark_time_us=*/200);
201  } else if (rst_info == kDifRstmgrResetInfoWatchdog) {
202  LOG_INFO("Booting for the third time due to wdog bite reset");
203  LOG_INFO("Last Booting");
204  LOG_INFO("Test finish");
205  return true;
206  }
207 
208  // Reset reason is also checked above, so this is not strictly necessary.
209  return false;
210 }