Software APIs
ast_clk_outs_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/testing/aon_timer_testutils.h"
9 #include "sw/device/lib/testing/clkmgr_testutils.h"
10 #include "sw/device/lib/testing/pwrmgr_testutils.h"
11 #include "sw/device/lib/testing/sensor_ctrl_testutils.h"
12 #include "sw/device/lib/testing/test_framework/check.h"
14 
15 OTTF_DEFINE_TEST_CONFIG();
16 
17 /**
18  * AST CLK OUTPUTS TEST
19  *
20  * This test measures clock counts with clkmgr frequency measurements,
21  * performing 100 measurements per round. Measurement errors (fast or slow
22  * clocks) are recorded as recoverable error in clkmgr.
23  *
24  * After 100 measurements, this configures the clock counters per external
25  * clock and low speed settings before entering low-power mode, where all but
26  * the aon clock are off. The expectation is that main and io clocks will
27  * report errors, but div2 and div4 should not.
28  *
29  * When the dut wakes up, another 100 measurements are done before the
30  * test finishes.
31  *
32  * Notice the test overrides the hardware behavior so it comes out with
33  * calibrated USB clock, otherwise the USB clock frequency will be incorrect.
34  * USB calibration should be a separate test, and may be vendor-specific.
35  */
36 enum {
37  kWaitForCSRPollingUs = 1, // 1us
38  kMeasurementsPerRound = 100,
39 };
40 
41 static dif_clkmgr_t clkmgr;
42 static dif_pwrmgr_t pwrmgr;
43 
44 static const dt_pwrmgr_t kPwrmgrDt = 0;
45 static_assert(kDtPwrmgrCount == 1, "this test expects a pwrmgr");
46 static const dt_aon_timer_t kAonTimerDt = 0;
47 static_assert(kDtAonTimerCount == 1, "this test expects an aon_timer");
48 static const dt_clkmgr_t kClkmgrDt = 0;
49 static_assert(kDtClkmgrCount >= 1, "this test expects a clkmgr");
50 static const dt_sensor_ctrl_t kSensorCtrlDt = 0;
51 static_assert(kDtSensorCtrlCount >= 1, "this test expects a sensor_ctrl");
52 
53 bool test_main(void) {
54  dif_sensor_ctrl_t sensor_ctrl;
55  dif_aon_timer_t aon_timer;
56 
57  uint32_t delay_micros = 0;
58  CHECK_STATUS_OK(aon_timer_testutils_get_us_from_aon_cycles(
59  kMeasurementsPerRound, &delay_micros));
60 
61  CHECK_DIF_OK(dif_clkmgr_init_from_dt(kClkmgrDt, &clkmgr));
62  CHECK_DIF_OK(dif_sensor_ctrl_init_from_dt(kSensorCtrlDt, &sensor_ctrl));
63  CHECK_DIF_OK(dif_pwrmgr_init_from_dt(kPwrmgrDt, &pwrmgr));
64  CHECK_DIF_OK(dif_aon_timer_init_from_dt(kAonTimerDt, &aon_timer));
65 
66  dif_pwrmgr_request_sources_t wakeup_sources;
67  CHECK_DIF_OK(dif_pwrmgr_find_request_source(
68  &pwrmgr, kDifPwrmgrReqTypeWakeup, dt_aon_timer_instance_id(kAonTimerDt),
69  kDtAonTimerWakeupWkupReq, &wakeup_sources));
70 
71  LOG_INFO("TEST: wait for ast init");
72  IBEX_SPIN_FOR(sensor_ctrl_ast_init_done(&sensor_ctrl), 1000);
73  LOG_INFO("TEST: done ast init");
74 
75  if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(&pwrmgr, 0)) == true) {
76  // At POR.
77  LOG_INFO("Run clock measurements right after POR");
78  CHECK_STATUS_OK(
79  clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
80  &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/false,
81  /*low_speed=*/false));
82  busy_spin_micros(delay_micros);
83 
84  // check results
85  CHECK_STATUS_OK(clkmgr_testutils_check_measurement_counts(&clkmgr));
86  CHECK_STATUS_OK(clkmgr_testutils_disable_clock_counts(&clkmgr));
87 
88  // Set wakeup timer to 100 us to have enough down time, and also wait before
89  // entering deep sleep to have a chance to measure before sleeping.
90  // As a side-effect of deep sleep the clock measurements are disabled, but
91  // recoverable errors are not cleared.
92  //
93  // Set the counters so we should get an error unless they are cleared.
94  uint64_t wakeup_threshold = kDeviceType == kDeviceSimVerilator ? 1000 : 100;
95  CHECK_STATUS_OK(
96  aon_timer_testutils_wakeup_config(&aon_timer, wakeup_threshold));
97 
98  LOG_INFO("Start clock measurements to cause an error for main and io clk.");
99  CHECK_STATUS_OK(
100  clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
101  &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/true,
102  /*low_speed=*/true));
103  // Disable writes to measure ctrl registers.
104  CHECK_DIF_OK(dif_clkmgr_measure_ctrl_disable(&clkmgr));
105 
106  busy_spin_micros(delay_micros);
107 
108  CHECK_STATUS_OK(pwrmgr_testutils_enable_low_power(
109  &pwrmgr, wakeup_sources, kDifPwrmgrDomainOptionUsbClockInActivePower));
110 
111  LOG_INFO("TEST: Issue WFI to enter deep sleep");
113 
114  } else if (UNWRAP(pwrmgr_testutils_is_wakeup_reason(
115  &pwrmgr, wakeup_sources)) == true) {
116  // Fail if some measurements are enabled.
117  bool all_disabled = UNWRAP(clkmgr_testutils_check_measurement_enables(
118  &clkmgr, kDifToggleDisabled));
119  CHECK(all_disabled);
120  // Check measurement control regwen is enabled.
121  dif_toggle_t state;
122  CHECK_DIF_OK(dif_clkmgr_measure_ctrl_get_enable(&clkmgr, &state));
123  CHECK(state == kDifToggleEnabled);
124  LOG_INFO("Check for all clock measurements disabled done");
125 
126  // Check we have a measurement error for the main clock.
127  dif_clkmgr_recov_err_codes_t expected_err_codes =
128  kDifClkmgrRecovErrTypeMainMeas | kDifClkmgrRecovErrTypeIoMeas;
130  CHECK_DIF_OK(dif_clkmgr_recov_err_code_get_codes(&clkmgr, &err_codes));
131  CHECK(err_codes == expected_err_codes,
132  "expected main and io clk measurement error 0x%x, but got 0x%x",
133  expected_err_codes, err_codes);
134 
135  // Clear measurement errors.
136  CHECK_DIF_OK(dif_clkmgr_recov_err_code_clear_codes(&clkmgr, UINT32_MAX));
137 
138  LOG_INFO("TEST: one more measurement");
139  CHECK_STATUS_OK(
140  clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
141  &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/false,
142  /*low_speed=*/false));
143  busy_spin_micros(delay_micros);
144  CHECK_STATUS_OK(clkmgr_testutils_check_measurement_counts(&clkmgr));
145  CHECK_STATUS_OK(clkmgr_testutils_disable_clock_counts(&clkmgr));
146 
147  LOG_INFO("TEST: done");
148  return true;
149  } else { // error
150  dif_pwrmgr_wakeup_reason_t wakeup_reason;
151  CHECK_DIF_OK(dif_pwrmgr_wakeup_reason_get(&pwrmgr, &wakeup_reason));
152  LOG_ERROR("Unexpected wakeup detected: type = %d, request_source = %d",
153  wakeup_reason.types, wakeup_reason.request_sources);
154  return false;
155  }
156 
157  return false;
158 }