Software APIs
sensor_ctrl_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 
10 #include "sw/device/lib/runtime/irq.h"
12 #include "sw/device/lib/testing/pwrmgr_testutils.h"
13 #include "sw/device/lib/testing/rv_plic_testutils.h"
14 #include "sw/device/lib/testing/test_framework/check.h"
16 
17 #include "sensor_ctrl_regs.h" // Generated.
18 
19 OTTF_DEFINE_TEST_CONFIG();
20 
21 static const dt_pwrmgr_t kPwrmgrDt = 0;
22 static_assert(kDtPwrmgrCount == 1, "this test expects a pwrmgr");
23 static const dt_rv_plic_t kRvPlicDt = 0;
24 static_assert(kDtRvPlicCount == 1, "this test expects exactly one rv_plic");
25 static const dt_sensor_ctrl_t kSensorCtrlDt = 0;
26 static_assert(kDtSensorCtrlCount == 1,
27  "this test expects exactly one sensor_ctrl");
28 
29 enum {
30  kPlicTarget = 0,
31 };
32 
33 static dif_pwrmgr_t pwrmgr;
34 static dif_rv_plic_t plic;
35 
36 static bool get_wakeup_status(void) {
37  dif_pwrmgr_request_sources_t wake_req = ~0u;
39  &pwrmgr, kDifPwrmgrReqTypeWakeup, &wake_req));
40  return (wake_req > 0);
41 }
42 
43 /**
44  * External interrupt handler.
45  */
46 bool ottf_handle_irq(uint32_t *exc_info, dt_instance_id_t devid,
47  dif_rv_plic_irq_id_t irq_id) {
48  if (devid == dt_pwrmgr_instance_id(kPwrmgrDt) &&
49  irq_id == dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup)) {
50  CHECK_DIF_OK(dif_pwrmgr_irq_acknowledge(&pwrmgr, kDtPwrmgrIrqWakeup));
51  return true;
52  } else {
53  return false;
54  }
55 }
56 
57 bool test_main(void) {
58  dif_sensor_ctrl_t sensor_ctrl;
59 
60  // Enable global and external IRQ at Ibex.
61  irq_global_ctrl(true);
62  irq_external_ctrl(true);
63 
64  // Initialize the PLIC.
65  CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &plic));
66 
67  // Initialize pwrmgr
68  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
69 
70  // Initialize sensor_ctrl
71  CHECK_DIF_OK(dif_sensor_ctrl_init_from_dt(kSensorCtrlDt, &sensor_ctrl));
72 
73  // Enable all the AON interrupts used in this test.
74  dif_rv_plic_irq_id_t plic_id =
75  dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup);
76  rv_plic_testutils_irq_range_enable(&plic, kPlicTarget, plic_id, plic_id);
77 
78  // Enable pwrmgr interrupt
79  CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled));
80 
81  // Capture the number of events to test
82  uint32_t sensor_ctrl_events = SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS;
83 
84  dif_pwrmgr_domain_config_t sleep_config =
85  kDifPwrmgrDomainOptionMainPowerInLowPower;
86 
87  // Clear any prior events before we start the test
88  for (size_t i = 0; i < sensor_ctrl_events; ++i) {
89  CHECK_DIF_OK(dif_sensor_ctrl_clear_recov_event(&sensor_ctrl, i));
90  }
91 
92  for (size_t i = 0; i < sensor_ctrl_events; ++i) {
93  LOG_INFO("Testing sensor_ctrl event %d", i);
94 
95  // Enable the alert on the sensor_ctrl side
96  CHECK_DIF_OK(
98 
99  // Setup event trigger
100  CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, i,
102 
103  // Normal sleep.
104  dif_pwrmgr_request_sources_t wakeup_sources;
105  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
106  &pwrmgr, kDifPwrmgrReqTypeWakeup,
107  dt_sensor_ctrl_instance_id(kSensorCtrlDt), kDtSensorCtrlWakeupWkupReq,
108  &wakeup_sources));
109  CHECK_STATUS_OK(pwrmgr_testutils_enable_low_power(&pwrmgr, wakeup_sources,
110  sleep_config));
111 
112  // Enter low power mode.
113  LOG_INFO("Issue WFI to enter sleep");
115 
116  // Wakeup from sleep.
117  LOG_INFO("Wake from sleep");
118 
120  CHECK_DIF_OK(dif_sensor_ctrl_get_recov_events(&sensor_ctrl, &events));
121 
122  if (events != (1 << i)) {
123  LOG_ERROR("Recoverable event 0x%x does not match expectation %d", events,
124  i);
125  }
126 
127  // Disable the alert on the sensor_ctrl side
128  CHECK_DIF_OK(
130 
131  // clear event trigger
132  CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, i,
134 
135  // since there is synchronization delay to trigger clearing and actual event
136  // de-assertion, clear and poll until it is finished before moving on
137  while (events) {
138  CHECK_DIF_OK(dif_sensor_ctrl_clear_recov_event(&sensor_ctrl, i));
139  CHECK_DIF_OK(dif_sensor_ctrl_get_recov_events(&sensor_ctrl, &events));
140  }
141 
142  // ensure the de-asserted events have cleared from the wakeup pipeline
143  // within 30us
144  IBEX_SPIN_FOR(!get_wakeup_status(), 30);
145  }
146 
147  return true;
148 }