Software APIs
sleep_pin_wake_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 
9 #include "sw/device/lib/runtime/irq.h"
11 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
12 #include "sw/device/lib/testing/pwrmgr_testutils.h"
13 #include "sw/device/lib/testing/rand_testutils.h"
14 #include "sw/device/lib/testing/rv_plic_testutils.h"
15 #include "sw/device/lib/testing/test_framework/check.h"
17 #include "sw/device/lib/testing/test_framework/ottf_utils.h"
18 
20 // Below includes are generated during compile time.
21 #include "flash_ctrl_regs.h"
22 #include "pinmux_regs.h"
23 
24 /* We need control flow for the ujson messages exchanged
25  * with the host in OTTF_WAIT_FOR on real devices. */
26 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true);
27 
28 static const dt_pwrmgr_t kPwrmgrDt = 0;
29 static_assert(kDtPwrmgrCount == 1, "this library expects exactly one pwrmgr");
30 static const dt_pinmux_t kPinmuxDt = 0;
31 static_assert(kDtPinmuxCount == 1, "this library expects exactly one pinmux");
32 static const dt_rv_plic_t kRvPlicDt = 0;
33 static_assert(kDtRvPlicCount == 1, "this library expects exactly one rv_plic");
34 static const dt_flash_ctrl_t kFlashCtrlDt = 0;
35 static_assert(kDtFlashCtrlCount >= 1,
36  "this library expects at least one flash_ctrl");
37 
38 // PLIC structures
39 static dif_pwrmgr_t pwrmgr;
40 static dif_pinmux_t pinmux;
41 static dif_rv_plic_t plic;
42 static dif_flash_ctrl_state_t flash_ctrl_state;
43 
44 enum {
45  kPlicTarget = 0,
46 };
47 
48 static const uint32_t kNumDio = 16; // top_earlgrey has 16 DIOs
49 
50 // kDirectDio is a list of Dio index that TB cannot control the PAD value.
51 // The list should be incremental order (see the code below)
52 #define NUM_DIRECT_DIO 5
53 static const uint32_t kDirectDio[NUM_DIRECT_DIO] = {6, 12, 13, 14, 15};
54 
55 // Preserve wakeup_detector_selected over multiple resets
56 OT_SET_BSS_SECTION(".non_volatile_scratch", uint32_t wakeup_detector_idx;)
57 
58 OTTF_BACKDOOR_VAR
59 int8_t sival_mio_pad = -1; // -1 means not assigned yet.
60 OTTF_BACKDOOR_VAR
61 int8_t sival_wakeup_detector_idx = -1; // -1 means not assigned yet.
62 OTTF_BACKDOOR_VAR
63 bool sival_ready_to_sleep = false;
64 
65 /**
66  * External interrupt handler.
67  */
68 bool ottf_handle_irq(uint32_t *exc_info, dt_instance_id_t devid,
69  dif_rv_plic_irq_id_t irq_id) {
70  if (devid == dt_pwrmgr_instance_id(kPwrmgrDt) &&
71  irq_id == dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup)) {
72  CHECK_DIF_OK(dif_pwrmgr_irq_acknowledge(&pwrmgr, kDtPwrmgrIrqWakeup));
73  return true;
74  } else {
75  return false;
76  }
77 }
78 
79 bool test_main(void) {
80  dif_pinmux_wakeup_config_t wakeup_cfg;
81 
82  // Default Deep Power Down
83  dif_pwrmgr_domain_config_t pwrmgr_domain_cfg = 0;
84 
85  // Enable global and external IRQ at Ibex.
86  irq_global_ctrl(true);
87  irq_external_ctrl(true);
88 
89  // Initialize power manager
90  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
91  CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &plic));
92  CHECK_DIF_OK(dif_pinmux_init_from_dt(kPinmuxDt, &pinmux));
93  CHECK_DIF_OK(
94  dif_flash_ctrl_init_state_from_dt(&flash_ctrl_state, kFlashCtrlDt));
95 
96  // Wakeup source for pinmux.
97  dif_pwrmgr_request_sources_t wakeup_sources;
98  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
99  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_pinmux_instance_id(kPinmuxDt),
100  kDtPinmuxWakeupPinWkupReq, &wakeup_sources));
101 
102  if (kDeviceType == kDeviceSimDV) {
103  // Enable access to flash for storing info across resets.
104  CHECK_STATUS_OK(
105  flash_ctrl_testutils_default_region_access(&flash_ctrl_state,
106  /*rd_en*/ true,
107  /*prog_en*/ true,
108  /*erase_en*/ true,
109  /*scramble_en*/ false,
110  /*ecc_en*/ false,
111  /*he_en*/ false));
112  }
113 
114  // Randomly pick one of the wakeup detectors
115  // only after the first boot.
116  dif_pinmux_index_t wakeup_detector_selected = 0;
117 
118  if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true) {
119  LOG_INFO("Test in POR phase");
120 
121  // After randomly generated wake detector index,
122  // store to non volatile area to preserve from the reset event.
123  wakeup_detector_selected =
124  rand_testutils_gen32_range(0, PINMUX_PARAM_N_WKUP_DETECT - 1);
125  if (kDeviceType == kDeviceSimDV) {
126  CHECK_STATUS_OK(flash_ctrl_testutils_write(
127  &flash_ctrl_state,
128  (uint32_t)(&wakeup_detector_idx) -
130  0, &wakeup_detector_selected, kDifFlashCtrlPartitionTypeData, 1));
131  }
132  LOG_INFO("detector %d is selected", wakeup_detector_selected);
133  // TODO(lowrisc/opentitan#15889): The weak pull on IOC3 needs to be
134  // disabled for this test. Remove this later.
135  dif_pinmux_pad_attr_t out_attr;
136  dif_pinmux_pad_attr_t in_attr = {0};
137  CHECK_DIF_OK(dif_pinmux_pad_write_attrs(&pinmux, kTopEarlgreyMuxedPadsIoc3,
138  kDifPinmuxPadKindMio, in_attr,
139  &out_attr));
140 
141  // This print is placed here on purpose.
142  // sv sequence is waiting for this print log followed by
143  // Pad Section. So do not put any other print between
144  // this LOG_INFO and LOG_INFO("Pad Selection");
145  LOG_INFO("pinmux_init end");
146  // Random choose low power or deep powerdown
147  uint32_t deep_powerdown_en = rand_testutils_gen32_range(0, 1);
148 
149  // Prepare which PAD SW want to select. In SiVal we only test the MIO pads,
150  // as the DIO ones are generally not testable with our setup.
151  uint32_t mio0_dio1 =
152  (kDeviceType == kDeviceSimDV) ? rand_testutils_gen32_range(0, 1) : 0;
153  uint32_t pad_sel = 0;
154 
155  // Enable AonWakeup Interrupt if normal sleep
156  if (deep_powerdown_en == 0) {
157  // Enable all the AON interrupts used in this test.
158  dif_rv_plic_irq_id_t irq_id =
159  dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup);
160  rv_plic_testutils_irq_range_enable(&plic, kPlicTarget, irq_id, irq_id);
161  // Enable pwrmgr interrupt
162  CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled));
163  }
164 
165  // SpiDev CLK(idx 12), CS#(idx 13), D0(idx 6) and SpiHost CLK (14), CS#
166  // (15) are directly connected to the SPI IF. Cannot control them. Roll 3
167  // less and compensated later.
168  if (mio0_dio1) {
169  // DIO
170  pad_sel = rand_testutils_gen32_range(0, kNumDio - 1 - NUM_DIRECT_DIO);
171 
172  for (int i = 0; i < NUM_DIRECT_DIO; i++) {
173  if (pad_sel >= kDirectDio[i]) {
174  pad_sel++;
175  }
176  }
177  LOG_INFO("Pad Selection: %d / %d", mio0_dio1, pad_sel);
178  } else {
179  // MIO: 0, 1 are tie-0, tie-1
180  if (kDeviceType == kDeviceSimDV) {
181  pad_sel = rand_testutils_gen32_range(2, kTopEarlgreyPinmuxInselLast);
182  } else {
183  OTTF_WAIT_FOR(sival_mio_pad != -1, 1000000);
184  pad_sel = (uint32_t)sival_mio_pad + 2; // skip 0, 1 (see above)
185  }
186 
187  LOG_INFO("Pad Selection: %d / %d", mio0_dio1, pad_sel - 2);
188  }
189 
190  if (mio0_dio1 == 0) {
191  // TODO: Check if the PAD is locked (kDifPinmuxLockTargetOutsel), then
192  // skip if locked.
193  // Turn off Pinmux output selection
194  CHECK_DIF_OK(dif_pinmux_output_select(
195  &pinmux, pad_sel - 2, kTopEarlgreyPinmuxOutselConstantHighZ));
196  }
197 
199  wakeup_cfg.signal_filter = false;
200  wakeup_cfg.pad_type = mio0_dio1;
201  wakeup_cfg.pad_select = pad_sel;
202 
203  // TODO: A better test would be to program ALL wakeup detectors with
204  // randomly chosen pin wakeup sources and prove the right wakeup source
205  // woke up the chip from sleep.
207  &pinmux, wakeup_detector_selected, wakeup_cfg));
208 
209  if (deep_powerdown_en == 0) {
210  CHECK_DIF_OK(dif_pwrmgr_get_domain_config(&pwrmgr, &pwrmgr_domain_cfg));
211  pwrmgr_domain_cfg |= kDifPwrmgrDomainOptionMainPowerInLowPower;
212  }
213 
214  if (kDeviceType != kDeviceSimDV) {
215  OTTF_WAIT_FOR(sival_ready_to_sleep != 0, 1000000);
216  }
217 
218  // Enter low power
219  CHECK_STATUS_OK(pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources,
220  pwrmgr_domain_cfg));
221 
222  LOG_INFO("Entering low power mode.");
224  }
225 
226  if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, wakeup_sources))) {
227  LOG_INFO("Test in post-sleep pin wakeup phase");
228  uint32_t wakeup_cause;
229  CHECK_DIF_OK(dif_pinmux_wakeup_cause_get(&pinmux, &wakeup_cause));
230  // Get the wakeup dectector index from stored variable.
231  if (kDeviceType == kDeviceSimDV) {
232  wakeup_detector_selected = wakeup_detector_idx;
233  } else {
234  OTTF_WAIT_FOR(sival_wakeup_detector_idx != -1, 1000000);
235  wakeup_detector_selected = (uint32_t)sival_wakeup_detector_idx;
236  }
237 
238  LOG_INFO("wakeup_cause: %x %d %d", wakeup_cause,
239  1 << wakeup_detector_selected, wakeup_detector_selected);
240  CHECK(wakeup_cause == 1 << wakeup_detector_selected);
241  CHECK_DIF_OK(
242  dif_pinmux_wakeup_detector_disable(&pinmux, wakeup_detector_selected));
243  return true;
244 
245  } else {
246  // Other wakeup. This is a failure.
247  dif_pwrmgr_wakeup_reason_t wakeup_reason;
248  CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason));
249  LOG_ERROR("Unexpected wakeup detected: type = %d, request_source = %d",
250  wakeup_reason.types, wakeup_reason.request_sources);
251  return false;
252  }
253 
254  return false;
255 }
256 
257 #undef NUM_DIRECT_DIO
258 #undef NUM_LOCKED_MIO