Software APIs
sysrst_ctrl_reset_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 
12 #include "sw/device/lib/testing/pwrmgr_testutils.h"
13 #include "sw/device/lib/testing/rstmgr_testutils.h"
14 #include "sw/device/lib/testing/sysrst_ctrl_testutils.h"
15 #include "sw/device/lib/testing/test_framework/check.h"
17 
18 OTTF_DEFINE_TEST_CONFIG();
19 
20 static dif_pwrmgr_t pwrmgr;
21 static dif_rstmgr_t rstmgr;
22 static dif_sysrst_ctrl_t sysrst_ctrl;
23 static dif_gpio_t gpio;
24 
25 static dif_pwrmgr_request_sources_t reset_sources, wakeup_sources,
26  other_wakeup_sources;
27 
28 static const dt_pwrmgr_t kPwrmgrDt = 0;
29 static_assert(kDtPwrmgrCount == 1, "this test expects a pwrmgr");
30 static const dt_pinmux_t kPinmuxDt = 0;
31 static_assert(kDtPinmuxCount == 1, "this test expects a pinmux");
32 static const dt_rstmgr_t kRstmgrDt = 0;
33 static_assert(kDtRstmgrCount == 1, "this test expects a rstmgr");
34 static const dt_gpio_t kGpioDt = 0;
35 static_assert(kDtGpioCount == 1, "this test expects a gpio");
36 static const dt_sysrst_ctrl_t kSysrstCtrlDt = 0;
37 static_assert(kDtSysrstCtrlCount == 1, "this test expects a sysrst_ctrl");
38 
39 enum {
40  kTestPhaseCheckComboReset = 0,
41  kTestPhaseCheckDeepSleepWakeup = 1,
42  kTestPhaseCheckDeepSleepReset = 2,
43  kTestPhaseFinalCheck = 3,
44 };
45 
46 // Threshold/Duration values are not specific to a real-world debounce
47 // scenario so are kept short to avoid excessive simulation time.
48 // Assuming a 5us aon clock period.
49 enum {
50  kDetectionTimeThreshold = 1024, // ~5ms
51  kEcResetDuration = 512, // ~2.5ms
52  kDebounceTimeThreshold = 128, // ~0.6ms
53 };
54 
55 enum {
56  kOutputNumMioPads = 6,
57 };
58 
59 static const dt_sysrst_ctrl_periph_io_t kPeripheralInputs[] = {
60  kDtSysrstCtrlPeriphIoKey0In, kDtSysrstCtrlPeriphIoKey1In,
61  kDtSysrstCtrlPeriphIoKey2In, kDtSysrstCtrlPeriphIoPwrbIn,
62  kDtSysrstCtrlPeriphIoAcPresent, kDtSysrstCtrlPeriphIoLidOpen,
63 };
64 
65 static const dt_pad_t kInputPadsDV[] = {
66  kDtPadIob3, kDtPadIob6, kDtPadIob8, kDtPadIob9, kDtPadIoc7, kDtPadIoc9,
67 };
68 
69 // We need different pins on the hyperdebug boards since certain
70 // pins are not routed to the hyperdebug.
71 static const dt_pad_t kInputPadsReal[] = {
72  kDtPadIor10, kDtPadIor11, kDtPadIor12, kDtPadIor5, kDtPadIor6, kDtPadIor7,
73 };
74 
75 // On DV this device is in the flash and written by the testbench.
76 static volatile const uint8_t kTestPhaseDV = 0;
77 // Mask of the GPIOs used on the real device to read the test phase.
78 static const uint32_t kGpioMask = 0x3;
79 
80 static void check_combo_reset(void) {
82  &sysrst_ctrl, kDifSysrstCtrlKeyCombo0,
86  .detection_time_threshold = kDetectionTimeThreshold,
87  .embedded_controller_reset_duration = kEcResetDuration,
89 
92  .debounce_time_threshold = kDebounceTimeThreshold,
93  .input_changes = kDifSysrstCtrlInputKey0H2L |
97  (dif_sysrst_ctrl_pin_config_t){.allow_one = true,
98  .allow_zero = true,
99  .enabled = kDifToggleEnabled,
100  .override_value = true}));
101  // Prepare rstmgr for a reset with sysrst_ctrl (source one).
102  CHECK_STATUS_OK(rstmgr_testutils_pre_reset(&rstmgr));
103  CHECK_DIF_OK(dif_pwrmgr_set_request_sources(
104  &pwrmgr, kDifPwrmgrReqTypeReset, reset_sources, kDifToggleEnabled));
105  // Issue WFI and wait for reset condition.
106  test_status_set(kTestStatusInWfi);
108 }
109 
110 static void check_deep_sleep_wakeup(void) {
112  &sysrst_ctrl, (dif_sysrst_ctrl_ulp_wakeup_config_t){
113  .ac_power_debounce_time_threshold = 0,
114  .lid_open_debounce_time_threshold = 0,
115  .power_button_debounce_time_threshold = 0,
116  .enabled = kDifToggleEnabled}));
117  // Setup low power.
118  // Wakeup source is from sysrst_ctrl (source one).
119  CHECK_STATUS_OK(rstmgr_testutils_pre_reset(&rstmgr));
120  CHECK_STATUS_OK(
121  pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources, 0));
122  // Issue WFI and wait for reset condition.
123  test_status_set(kTestStatusInWfi);
125 }
126 
127 static void check_deep_sleep_reset(void) {
129  &sysrst_ctrl, kDifSysrstCtrlKeyCombo1,
133  .detection_time_threshold = kDetectionTimeThreshold,
134  .embedded_controller_reset_duration = kEcResetDuration,
138  (dif_sysrst_ctrl_pin_config_t){.allow_one = true,
139  .allow_zero = true,
140  .enabled = kDifToggleEnabled,
141  .override_value = true}));
144  .debounce_time_threshold = kDebounceTimeThreshold,
145  .input_changes = kDifSysrstCtrlInputKey2H2L |
147  // Setup low power.
148  // Reset source is from sysrst_ctrl (source one).
149  CHECK_STATUS_OK(rstmgr_testutils_pre_reset(&rstmgr));
150  CHECK_DIF_OK(dif_pwrmgr_set_request_sources(
151  &pwrmgr, kDifPwrmgrReqTypeReset, reset_sources, kDifToggleEnabled));
152  // Enable low power with wakeup source other than
153  // sysrst_ctrl (e.g. source two) as we don't want
154  // a wakeup request but instead a reset.
155  CHECK_STATUS_OK(
156  pwrmgr_testutils_enable_low_power(&pwrmgr, other_wakeup_sources, 0));
157  // Issue WFI and wait for reset condition.
158  test_status_set(kTestStatusInWfi);
160 }
161 
162 bool test_main(void) {
163  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
164  CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
165  CHECK_DIF_OK(dif_sysrst_ctrl_init_from_dt(kSysrstCtrlDt, &sysrst_ctrl));
166  CHECK_DIF_OK(dif_gpio_init_from_dt(kGpioDt, &gpio));
167 
168  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
169  &pwrmgr, kDifPwrmgrReqTypeWakeup,
170  dt_sysrst_ctrl_instance_id(kSysrstCtrlDt), kDtSysrstCtrlWakeupWkupReq,
171  &wakeup_sources));
172  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
173  &pwrmgr, kDifPwrmgrReqTypeReset,
174  dt_sysrst_ctrl_instance_id(kSysrstCtrlDt), kDtSysrstCtrlResetReqRstReq,
175  &reset_sources));
176  // Any wakeup source different from sysrst_ctrl.
177  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
178  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_pinmux_instance_id(kPinmuxDt),
179  kDtPinmuxWakeupPinWkupReq, &other_wakeup_sources));
180 
181  dif_rstmgr_reset_info_bitfield_t rstmgr_reset_info;
182  rstmgr_reset_info = rstmgr_testutils_reason_get();
183 
184  dif_pinmux_t pinmux;
185  CHECK_DIF_OK(dif_pinmux_init_from_dt(kPinmuxDt, &pinmux));
186  const dt_pad_t *kInputPads =
187  kDeviceType == kDeviceSimDV ? kInputPadsDV : kInputPadsReal;
188  for (int i = 0; i < kOutputNumMioPads; ++i) {
189  CHECK_DIF_OK(dif_pinmux_mio_select_input(
190  &pinmux, dt_sysrst_ctrl_periph_io(kSysrstCtrlDt, kPeripheralInputs[i]),
191  kInputPads[i]));
192  }
193  // On real devices, we also need to configure the DIO pins and two more pins
194  // to read the test phase.
195  if (kDeviceType != kDeviceSimDV) {
196  sysrst_ctrl_testutils_setup_dio(&pinmux);
197  CHECK_DIF_OK(dif_pinmux_mio_select_input(
198  &pinmux, dt_gpio_periph_io(kGpioDt, kDtGpioPeriphIoGpio0), kDtPadIob0));
199  CHECK_DIF_OK(dif_pinmux_mio_select_input(
200  &pinmux, dt_gpio_periph_io(kGpioDt, kDtGpioPeriphIoGpio1), kDtPadIob1));
201  }
202 
205 
206  // On real device, we cannot do backdoor writes the flash so we read the
207  // test phase from GPIOs.
208  uint8_t kTestPhase = kTestPhaseDV;
209  if (kDeviceType != kDeviceSimDV) {
210  uint32_t gpio_state;
211  CHECK_DIF_OK(dif_gpio_read_all(&gpio, &gpio_state));
212  kTestPhase = gpio_state & kGpioMask;
213  }
214  LOG_INFO("test phase: %u", kTestPhase);
215 
216  switch (kTestPhase) {
217  case kTestPhaseCheckComboReset:
218  CHECK(rstmgr_reset_info == kDifRstmgrResetInfoPor);
219  check_combo_reset();
220  break;
221  case kTestPhaseCheckDeepSleepWakeup:
222  CHECK(rstmgr_reset_info == kDifRstmgrResetInfoSysRstCtrl);
223  check_deep_sleep_wakeup();
224  break;
225  case kTestPhaseCheckDeepSleepReset:
226  CHECK(rstmgr_reset_info == kDifRstmgrResetInfoLowPowerExit);
227  check_deep_sleep_reset();
228  break;
229  case kTestPhaseFinalCheck:
230  CHECK(rstmgr_reset_info ==
231  (kDifRstmgrResetInfoSysRstCtrl | kDifRstmgrResetInfoLowPowerExit));
232  return true;
233  break;
234  default:
235  LOG_ERROR("Unexpected test phase : %d", kTestPhase);
236  break;
237  }
238  return false;
239 }