Software APIs
clkmgr_sleep_frequency_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 
8 #include "sw/device/lib/runtime/irq.h"
10 #include "sw/device/lib/testing/aon_timer_testutils.h"
11 #include "sw/device/lib/testing/clkmgr_testutils.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/sensor_ctrl_testutils.h"
15 #include "sw/device/lib/testing/test_framework/check.h"
17 
19 #include "sw/device/lib/testing/autogen/isr_testutils.h"
20 
21 OTTF_DEFINE_TEST_CONFIG();
22 
23 /**
24  * This test measure clock counts with clkmgr frequency measurements, performing
25  * 100 measurements per round. Measurement errors (fast or slow clocks) are
26  * recorded as recoverable error in clkmgr.
27  *
28  * After 100 measurements, test kicks in regular sleep with IO and USB
29  * clocks turned off. Once the chip wakes up the measurements should be
30  * enabled, but no errors should be found even for stopped clocks.
31  */
32 enum {
33  kWaitForCSRPollingMicros = 1,
34  kMeasurementsPerRound = 100,
35  kPlicTarget = 0,
36 
37 };
38 
39 static const dt_pwrmgr_t kPwrmgrDt = 0;
40 static_assert(kDtPwrmgrCount == 1, "this test expects a pwrmgr");
41 static const dt_aon_timer_t kAonTimerDt = 0;
42 static_assert(kDtAonTimerCount == 1, "this test expects an aon_timer");
43 static const dt_clkmgr_t kClkmgrDt = 0;
44 static_assert(kDtClkmgrCount == 1, "this test expects a clkmgr");
45 static const dt_sensor_ctrl_t kSensorCtrlDt = 0;
46 static_assert(kDtSensorCtrlCount >= 1, "this test expects a sensor_ctrl");
47 static const dt_rv_plic_t kRvPlicDt = 0;
48 static_assert(kDtRvPlicCount == 1, "this test expects a rv_plic");
49 
50 static dif_clkmgr_t clkmgr;
51 static dif_pwrmgr_t pwrmgr;
52 static dif_rv_plic_t rv_plic;
53 
54 static volatile bool isr_entered;
55 
56 /**
57  * External interrupt handler.
58  */
59 bool ottf_handle_irq(uint32_t *exc_info, dt_instance_id_t devid,
60  dif_rv_plic_irq_id_t irq_id) {
61  if (devid == dt_pwrmgr_instance_id(kPwrmgrDt) &&
62  irq_id == dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup)) {
63  CHECK_DIF_OK(dif_pwrmgr_irq_acknowledge(&pwrmgr, kDtPwrmgrIrqWakeup));
64  isr_entered = true;
65  return true;
66  } else {
67  return false;
68  }
69 }
70 
71 bool test_main(void) {
72  dif_sensor_ctrl_t sensor_ctrl;
73  dif_aon_timer_t aon_timer;
74 
75  uint32_t delay_micros = 0;
76  CHECK_STATUS_OK(aon_timer_testutils_get_us_from_aon_cycles(
77  kMeasurementsPerRound, &delay_micros));
78 
79  // Enable global and external IRQ at Ibex.
80  irq_global_ctrl(true);
81  irq_external_ctrl(true);
82 
83  CHECK_DIF_OK(dif_clkmgr_init_from_dt(kClkmgrDt, &clkmgr));
84  CHECK_DIF_OK(dif_sensor_ctrl_init_from_dt(kSensorCtrlDt, &sensor_ctrl));
85  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
86  CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
87  CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &rv_plic));
88 
89  dif_pwrmgr_request_sources_t wakeup_sources;
90  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
91  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_aon_timer_instance_id(kAonTimerDt),
92  kDtAonTimerWakeupWkupReq, &wakeup_sources));
93 
94  LOG_INFO("TEST: wait for ast init");
95  IBEX_SPIN_FOR(sensor_ctrl_ast_init_done(&sensor_ctrl), 1000);
96  LOG_INFO("TEST: done ast init");
97 
98  CHECK(UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true);
99 
100  CHECK_STATUS_OK(clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
101  &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/false,
102  /*low_speed=*/false));
103  busy_spin_micros(delay_micros);
104 
105  // check results
106  CHECK_STATUS_OK(clkmgr_testutils_check_measurement_counts(&clkmgr));
107  CHECK_STATUS_OK(clkmgr_testutils_disable_clock_counts(&clkmgr));
108 
109  // Start new round of measurements.
110  CHECK_STATUS_OK(clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
111  &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/false,
112  /*low_speed=*/false));
113 
114  busy_spin_micros(delay_micros);
115 
116  // Set wakeup timer to 100 us to have enough down time, and also wait before
117  // entering sleep to have a chance to measure before sleeping. With normal
118  // sleep all measurements should remain enabled, and there should be no
119  // errors for clocks that were selectively turned off.
120  uint64_t wakeup_threshold = kDeviceType == kDeviceSimVerilator ? 1000 : 100;
121  CHECK_STATUS_OK(
122  aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold));
123 
124  // Enable all the AON interrupts used in this test.
125  dif_rv_plic_irq_id_t irq_id =
126  dt_pwrmgr_irq_to_plic_id(kPwrmgrDt, kDtPwrmgrIrqWakeup);
127  rv_plic_testutils_irq_range_enable(&rv_plic, kPlicTarget, irq_id, irq_id);
128  CHECK_DIF_OK(dif_pwrmgr_irq_set_enabled(&pwrmgr, 0, kDifToggleEnabled));
129 
130  // Put chip in normal sleep, and keep Core clock running. All io and usb
131  // clocks are stopped, but we expect the stoppage won't trigger errors.
132  CHECK_STATUS_OK(pwrmgr_testutils_enable_low_power(
133  &pwrmgr, /*wakeups=*/wakeup_sources,
135  kDifPwrmgrDomainOptionUsbClockInActivePower |
136  kDifPwrmgrDomainOptionMainPowerInLowPower));
137 
138  LOG_INFO("TEST: Issue WFI to enter sleep");
140 
141  CHECK(isr_entered);
142 
143  // Interrupt happened. Check the measurement state.
144  CHECK_STATUS_OK(clkmgr_testutils_check_measurement_counts(&clkmgr));
145  bool all_enabled = UNWRAP(
146  clkmgr_testutils_check_measurement_enables(&clkmgr, kDifToggleEnabled));
147  CHECK(all_enabled);
148 
149  return true;
150 }