Software APIs
rv_dm_access_after_wakeup.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 
10 #include "sw/device/lib/runtime/irq.h"
12 #include "sw/device/lib/testing/aon_timer_testutils.h"
13 #include "sw/device/lib/testing/pwrmgr_testutils.h"
14 #include "sw/device/lib/testing/rstmgr_testutils.h"
15 #include "sw/device/lib/testing/rv_plic_testutils.h"
16 #include "sw/device/lib/testing/test_framework/check.h"
18 #include "sw/device/lib/testing/test_framework/ottf_utils.h"
19 #include "sw/device/lib/testing/test_framework/status.h"
20 
21 #include "pwrmgr_regs.h"
22 
23 /*
24  * RV_DM access after wakeup test.
25  */
26 
27 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true);
28 
29 enum {
30  kSoftwareBarrierTimeoutUsec = 1000000,
31  kPlicTarget = 0,
32 };
33 
34 // This variable will be updated by the DV environment.
35 OT_SECTION(".rodata")
36 static volatile const uint8_t kSoftwareBarrierDv = 0;
37 
38 // This variable will be updated by the test host.
39 OT_SECTION(".data")
40 static volatile const uint8_t kSoftwareBarrierHost = 0;
41 
42 static_assert(kDtPwrmgrCount == 1, "this test expects exactly one pwrmgr");
43 static const dt_pwrmgr_t kPwrmgrDt = 0;
44 static_assert(kDtRvPlicCount == 1, "this test expects exactly one rv_plic");
45 static const dt_rv_plic_t kRvPlicDt = 0;
46 static_assert(kDtSysrstCtrlCount >= 1,
47  "this test expects at least one sysrst_ctrl");
48 static const dt_sysrst_ctrl_t kSysrtCtrlDt = 0;
49 static_assert(kDtPinmuxCount == 1, "this test expects exactly one pinmux");
50 static const dt_pinmux_t kPinmuxDt = 0;
51 
52 // Handle to the plic
53 dif_rv_plic_t rv_plic;
54 
55 /**
56  * External interrupt handler.
57  *
58  * Simply claim the interrupt and does nothing else.
59  */
60 void ottf_external_isr(uint32_t *exc_info) {
61  dif_rv_plic_irq_id_t plic_irq_id;
62  CHECK_DIF_OK(dif_rv_plic_irq_claim(&rv_plic, kPlicTarget, &plic_irq_id));
63 }
64 
65 /**
66  * Put the device to sleep.
67  *
68  * @param pwrmgr A handle to the power manager.
69  * @param deep_sleep Whether or not to enter a deep sleep.
70  */
71 static void put_to_sleep(dif_pwrmgr_t *pwrmgr, bool deep_sleep) {
73  CHECK_DIF_OK(dif_pwrmgr_get_domain_config(pwrmgr, &cfg));
74  if (deep_sleep) {
75  cfg &= ~kDifPwrmgrDomainOptionMainPowerInLowPower;
76  } else {
77  cfg |= kDifPwrmgrDomainOptionMainPowerInLowPower;
78  }
79 
80  dif_pwrmgr_request_sources_t wakeup_sources;
81  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
82  pwrmgr, kDifPwrmgrReqTypeWakeup, dt_sysrst_ctrl_instance_id(kSysrtCtrlDt),
83  kDtSysrstCtrlWakeupWkupReq, &wakeup_sources));
84  CHECK_STATUS_OK(
85  pwrmgr_testutils_enable_low_power(pwrmgr, wakeup_sources, cfg));
86  LOG_INFO("%s",
87  deep_sleep ? "Entering deep sleep." : "Entering normal sleep.");
89 }
90 
91 bool test_main(void) {
92  // Enable global and external IRQ at Ibex.
93  irq_global_ctrl(true);
94  irq_external_ctrl(true);
95 
96  dif_pinmux_t pinmux;
97  dif_pwrmgr_t pwrmgr;
98  dif_sysrst_ctrl_t sysrst_ctrl;
99 
100  CHECK_DIF_OK(dif_pinmux_init_from_dt(kPinmuxDt, &pinmux));
101  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
102  CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &rv_plic));
103  CHECK_DIF_OK(dif_sysrst_ctrl_init_from_dt(kSysrtCtrlDt, &sysrst_ctrl));
104 
105  const volatile uint8_t *const software_barrier = (kDeviceType == kDeviceSimDV)
106  ? &kSoftwareBarrierDv
107  : &kSoftwareBarrierHost;
108 
109  switch (rstmgr_testutils_reason_get()) {
110  case kDifRstmgrResetInfoPor: // The first power-up.
111  LOG_INFO("Software Setup.");
112  // Wait for sequence to run its checks.
113  OTTF_WAIT_FOR(*software_barrier == 1, kSoftwareBarrierTimeoutUsec);
114 
115  // Enable all the AON interrupts used in this test.
116  dif_rv_plic_irq_id_t plic_id =
117  dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup);
118  rv_plic_testutils_irq_range_enable(&rv_plic, kPlicTarget, plic_id,
119  plic_id);
120 
121  // Enable pwrmgr interrupt.
122  CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, kDifPwrmgrIrqWakeup,
124 
125  // Set up power button as wake up source.
128  .debounce_time_threshold = 1, // 5us
129  };
130  CHECK_DIF_OK(
131  dif_sysrst_ctrl_input_change_detect_configure(&sysrst_ctrl, config));
132  CHECK_DIF_OK(dif_pinmux_mio_select_input(
133  &pinmux,
134  dt_sysrst_ctrl_periph_io(kSysrtCtrlDt, kDtSysrstCtrlPeriphIoPwrbIn),
135  kDtPadIor13));
136 
137  // Put the device in a normal sleep.
138  put_to_sleep(&pwrmgr, /*deep_sleep=*/false);
139  LOG_INFO("Waking up from normal sleep.");
140 
141  // Clean up wakeup source after sleep.
142  CHECK_DIF_OK(dif_sysrst_ctrl_ulp_wakeup_clear_status(&sysrst_ctrl));
143 
144  // Wait for sequence to run its checks.
145  OTTF_WAIT_FOR(*software_barrier == 2, kSoftwareBarrierTimeoutUsec);
146 
147  // Put the device in a deep sleep.
148  put_to_sleep(&pwrmgr, /*deep_sleep=*/true);
149  break;
150 
151  case kDifRstmgrResetInfoLowPowerExit: // The power up after deep sleep.
152  LOG_INFO("Waking up from deep sleep.");
153 
154  // Wait for sequence to finish before returning.
155  OTTF_WAIT_FOR(*software_barrier == 3, kSoftwareBarrierTimeoutUsec);
156  return true;
157 
158  default:
159  LOG_ERROR("Device was reset by an unexpected source.");
160  break;
161  }
162  return false;
163 }