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