Software APIs
sysrst_ctrl_ulp_z3_wakeup_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 
6 #include "sw/device/lib/base/status.h"
14 #include "sw/device/lib/testing/pwrmgr_testutils.h"
15 #include "sw/device/lib/testing/rstmgr_testutils.h"
16 #include "sw/device/lib/testing/sysrst_ctrl_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
19 #include "sw/device/lib/testing/test_framework/ottf_utils.h"
20 
21 /* We need control flow for the ujson messages exchanged
22  * with the host in OTTF_WAIT_FOR on real devices. */
23 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true);
24 
25 static const dt_pwrmgr_t kPwrmgrDt = 0;
26 static_assert(kDtPwrmgrCount == 1, "this test expects a pwrmgr");
27 static const dt_pinmux_t kPinmuxDt = 0;
28 static_assert(kDtPinmuxCount == 1, "this test expects a pinmux");
29 static const dt_rstmgr_t kRstmgrDt = 0;
30 static_assert(kDtRstmgrCount == 1, "this test expects a rstmgr");
31 static const dt_gpio_t kGpioDt = 0;
32 static_assert(kDtGpioCount == 1, "this test expects a gpio");
33 static const dt_sysrst_ctrl_t kSysrstCtrlDt = 0;
34 static_assert(kDtSysrstCtrlCount == 1, "this test expects a sysrst_ctrl");
35 
36 // This is updated by the sv/host component of the test.
37 // On DV, we must use variables in flash but on a real device,
38 // we must use variables in RAM.
39 OT_SECTION(".rodata")
40 static volatile const uint8_t kTestPhaseDV;
41 
42 static dif_pwrmgr_t pwrmgr;
43 static dif_rstmgr_t rstmgr;
44 static dif_pinmux_t pinmux;
45 static dif_sysrst_ctrl_t sysrst_ctrl;
46 static dif_gpio_t gpio;
47 
48 enum {
49  kNumMioInPads = 3,
50  kNumMioOutPads = 1,
51  kTestPhaseTimeoutUsecDV = 500,
52  kTestPhaseTimeoutUsecReal = 1000000,
53  // This means 20 aon_clk ticks ~= 20 * 5 us = 100 us
54  kDebounceTimer = 20,
55 };
56 
57 enum {
58  kTestPhaseInit = 0,
59  kTestPhaseDriveInitial = 1,
60  kTestPhaseWaitNoWakeup = 2,
61  kTestPhaseWaitWakeup = 3,
62  kTestPhaseDone = 4,
63 };
64 
65 static const dt_sysrst_ctrl_periph_io_t kPeripheralInputs[] = {
66  kDtSysrstCtrlPeriphIoPwrbIn,
67  kDtSysrstCtrlPeriphIoAcPresent,
68  kDtSysrstCtrlPeriphIoLidOpen,
69 };
70 
71 static const dt_pad_t kInputPadsDV[] = {
72  kDtPadIor13,
73  kDtPadIoc7,
74  kDtPadIoc9,
75 };
76 
77 static const dt_pad_t kInputPadsReal[] = {
78  kDtPadIor10,
79  kDtPadIor11,
80  kDtPadIor12,
81 };
82 
83 static const dt_sysrst_ctrl_periph_io_t kPeripheralOutputs[] = {
84  kDtSysrstCtrlPeriphIoZ3Wakeup,
85 };
86 
87 static const dt_pad_t kOutputPadsDV[] = {
88  kDtPadIob7,
89 };
90 
91 static const dt_pad_t kOutputPadsReal[] = {
92  kDtPadIor5,
93 };
94 
95 // Mask of the GPIOs used on the real device to read the test phase.
96 static const uint32_t kGpioMask = 0x7;
97 
98 /**
99  * Sets up the pinmux to assign input and output pads to the sysrst_ctrl
100  * peripheral as required.
101  */
102 static void pinmux_setup(void) {
103  const dt_pad_t *kInputPads =
104  kDeviceType == kDeviceSimDV ? kInputPadsDV : kInputPadsReal;
105  for (int i = 0; i < kNumMioInPads; ++i) {
106  CHECK_DIF_OK(dif_pinmux_mio_select_input(
107  &pinmux, dt_sysrst_ctrl_periph_io(kSysrstCtrlDt, kPeripheralInputs[i]),
108  kInputPads[i]));
109  }
110 
111  const dt_pad_t *kOutputPads =
112  kDeviceType == kDeviceSimDV ? kOutputPadsDV : kOutputPadsReal;
113  for (int i = 0; i < kNumMioOutPads; ++i) {
114  CHECK_DIF_OK(dif_pinmux_mio_select_output(
115  &pinmux, kOutputPads[i],
116  dt_sysrst_ctrl_periph_io(kSysrstCtrlDt, kPeripheralOutputs[i])));
117  }
118  sysrst_ctrl_testutils_setup_dio(&pinmux);
119  sysrst_ctrl_testutils_release_dio(&sysrst_ctrl, true, true);
120 }
121 
122 static uint8_t read_phase_pins(void) {
123  uint32_t gpio_state;
124  CHECK_DIF_OK(dif_gpio_read_all(&gpio, &gpio_state));
125  // Since the host may not be able to change all pins atomically, we use
126  // a Gray code encoding so that it suffices to change one pin to go to
127  // the next phase.
128  static const uint8_t kGrayCode[] = {0, 1, 3, 2, 7, 6, 4, 5};
129  return kGrayCode[gpio_state & kGpioMask];
130 }
131 
132 /**
133  * Waits for `kTestPhase` variable to be changed by a backdoor overwrite
134  * from the testbench in chip_sw_<testname>_vseq.sv. This will indicate that
135  * the testbench is ready to proceed with the next phase of the test.
136  *
137  * Backdoor overwrites don't invalidate the read caches, so this explicitly
138  * flushes them before updating the value.
139  */
140 static status_t wait_next_test_phase(uint8_t prior_phase) {
141  // Set WFI status for testbench synchronization,
142  // no actual WFI instruction is issued.
143  test_status_set(kTestStatusInWfi);
144  test_status_set(kTestStatusInTest);
145  LOG_INFO("wait_next_test_phase after %d", prior_phase);
146  if (kDeviceType == kDeviceSimDV) {
147  IBEX_TRY_SPIN_FOR(OTTF_BACKDOOR_READ(kTestPhaseDV) != prior_phase,
148  kTestPhaseTimeoutUsecDV);
149  LOG_INFO("Read test phase 0x%x", kTestPhaseDV);
150  } else {
151  IBEX_TRY_SPIN_FOR(read_phase_pins() != prior_phase,
152  kTestPhaseTimeoutUsecReal);
153  }
154  return OK_STATUS();
155 }
156 
157 /**
158  * Configure *_debounce_ctl and then enable ULP wakeup.
159  */
160 static void configure_wakeup(void) {
162 
163  // Keep toggle disabled when writing debounce configuration
164  wakeup_config.enabled = kDifToggleDisabled;
165  wakeup_config.ac_power_debounce_time_threshold = kDebounceTimer;
166  wakeup_config.lid_open_debounce_time_threshold = kDebounceTimer;
167  wakeup_config.power_button_debounce_time_threshold = kDebounceTimer;
168 
169  CHECK_DIF_OK(
170  dif_sysrst_ctrl_ulp_wakeup_configure(&sysrst_ctrl, wakeup_config));
171 
172  CHECK_DIF_OK(
174 }
175 
176 static void go_to_sleep(void) {
177  // Wakeup source is from sysrst_ctrl.
178  dif_pwrmgr_request_sources_t wakeup_sources;
179  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
180  &pwrmgr, kDifPwrmgrReqTypeWakeup,
181  dt_sysrst_ctrl_instance_id(kSysrstCtrlDt), kDtSysrstCtrlWakeupWkupReq,
182  &wakeup_sources));
183 
184  LOG_INFO("Going to sleep.");
185  test_status_set(kTestStatusInWfi);
186  CHECK_STATUS_OK(rstmgr_testutils_pre_reset(&rstmgr));
187  CHECK_STATUS_OK(
188  pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources,
189  /*pwrmgr_domain_config=*/0));
191 }
192 
193 static bool reset_is_low_power_exit(void) {
194  dif_rstmgr_reset_info_bitfield_t rst_info = rstmgr_testutils_reason_get();
195  rstmgr_testutils_reason_clear();
196  return rst_info == kDifRstmgrResetInfoLowPowerExit;
197 }
198 
199 static bool has_wakeup_happened(void) {
200  bool wakeup_detected;
201  CHECK_DIF_OK(
202  dif_sysrst_ctrl_ulp_wakeup_get_status(&sysrst_ctrl, &wakeup_detected));
203  return wakeup_detected;
204 }
205 
206 bool test_main(void) {
207  CHECK_DIF_OK(dif_sysrst_ctrl_init_from_dt(kSysrstCtrlDt, &sysrst_ctrl));
208  CHECK_DIF_OK(dif_pinmux_init_from_dt(kPinmuxDt, &pinmux));
209  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
210  CHECK_DIF_OK(dif_rstmgr_init_from_dt(kRstmgrDt, &rstmgr));
211  CHECK_DIF_OK(dif_gpio_init_from_dt(kGpioDt, &gpio));
212 
213  // In DV, we use flash backdoor writes to store the phase.
214  // On real devices, we cannot store it in RAM since the wakeup will erase
215  // it so use three pins to read the test phase.
216  if (kDeviceType != kDeviceSimDV) {
217  CHECK_DIF_OK(dif_pinmux_mio_select_input(
218  &pinmux, dt_gpio_periph_io(kGpioDt, kDtGpioPeriphIoGpio0), kDtPadIob0));
219  CHECK_DIF_OK(dif_pinmux_mio_select_input(
220  &pinmux, dt_gpio_periph_io(kGpioDt, kDtGpioPeriphIoGpio1), kDtPadIob1));
221  CHECK_DIF_OK(dif_pinmux_mio_select_input(
222  &pinmux, dt_gpio_periph_io(kGpioDt, kDtGpioPeriphIoGpio2), kDtPadIob2));
223  }
224  LOG_INFO("reset");
225 
226  while (true) {
227  uint8_t current_test_phase =
228  kDeviceType == kDeviceSimDV ? kTestPhaseDV : read_phase_pins();
229  LOG_INFO("Test phase %d", current_test_phase);
230  switch (current_test_phase) {
231  case kTestPhaseInit:
232  pinmux_setup();
233  break;
234  case kTestPhaseDriveInitial:
235  configure_wakeup();
236  LOG_INFO("kTestPhaseDriveInitial");
237  break;
238  case kTestPhaseWaitNoWakeup:
239  CHECK(!reset_is_low_power_exit());
240  CHECK(!has_wakeup_happened());
241  LOG_INFO("kTestPhaseWaitNoWakeup");
242  go_to_sleep();
243  break;
244  case kTestPhaseWaitWakeup:
245  CHECK(reset_is_low_power_exit());
246  CHECK(has_wakeup_happened());
247  LOG_INFO("kTestPhaseWaitWakeup");
248  break;
249  case kTestPhaseDone:
250  // End of test.
251  return true;
252  default:
253  LOG_ERROR("Unexpected test phase : %d", current_test_phase);
254  LOG_INFO("END");
255  break;
256  }
257  status_t status = wait_next_test_phase(current_test_phase);
258  CHECK_STATUS_OK(status);
259  if (!status_ok(status)) {
260  return false;
261  }
262  }
263  return true;
264 }