5#include "sw/device/lib/testing/clkmgr_testutils.h"
10#define MODULE_ID MAKE_MODULE_ID('c', 'm', 't')
12static_assert(kDtClkmgrCount == 1,
13 "this code assumes that there is a single clkmgr");
18 kMaxMeasureClockCount = kDtClockCount,
24extern bool clkmgr_testutils_get_trans_clock_status(
27extern status_t clkmgr_testutils_check_trans_clock_gating(
29 bool exp_clock_enabled, uint32_t timeout_usec);
37} expected_count_info_t;
42static size_t dt_clk_to_meas_clk[kDtClockCount];
45static expected_count_info_t kNoJitterCountInfos[kMaxMeasureClockCount];
48static expected_count_info_t kJitterCountInfos[kMaxMeasureClockCount];
55static uint32_t kVariabilityPercentage = 5;
60static uint32_t kJitterVariabilityPercentage = 12;
64static inline uint32_t get_count_variability(uint32_t cycles,
65 uint32_t variability_percentage) {
66 return ((cycles * variability_percentage) + 99) / 100 + 1;
69static const char *measure_clock_name(
const dif_clkmgr_t *clkmgr,
70 dif_clkmgr_measure_clock_t clock) {
74 return "<no dt info>";
77 return "<invalid clock>";
83#ifdef OPENTITAN_CLKMGR_HAS_MEAS_CTRL_MAIN
87#ifdef OPENTITAN_CLKMGR_HAS_MEAS_CTRL_IO
91#ifdef OPENTITAN_CLKMGR_HAS_MEAS_CTRL_IO_DIV2
95#ifdef OPENTITAN_CLKMGR_HAS_MEAS_CTRL_IO_DIV4
99#ifdef OPENTITAN_CLKMGR_HAS_MEAS_CTRL_USB
108static uint32_t cast_safely(uint64_t val) {
109 CHECK(val <= UINT32_MAX);
110 return (uint32_t)val;
122 for (
dt_clock_t dt_clk = 0; dt_clk < kDtClockCount; dt_clk++) {
127 for (
size_t clk_idx = 0;
130 dt_clk_to_meas_clk[clk_dt] = clk_idx;
137 uint32_t clk_count = cast_safely(
138 udiv64_slow(clk_freq_hz, aon_clk_freq_hz, NULL));
139 uint32_t variability =
140 get_count_variability(clk_count, kVariabilityPercentage);
141 LOG_INFO(
"Variability for %s(%d) %d is %d",
142 measure_clock_name(clkmgr, clk_idx), clk_idx, clk_count,
147 kNoJitterCountInfos[clk_idx] = (expected_count_info_t){
148 .count = clk_count - 1, .variability = variability};
153 if (clk_dt != main_clk_dt) {
154 kJitterCountInfos[clk_idx] = kNoJitterCountInfos[clk_idx];
156 kJitterCountInfos[clk_idx] = (expected_count_info_t){
157 .count = clk_count - clk_count / 10,
158 .variability = get_count_variability(clk_count - clk_count / 10,
159 kJitterVariabilityPercentage)};
166status_t clkmgr_testutils_enable_clock_count(
const dif_clkmgr_t *clkmgr,
167 dif_clkmgr_measure_clock_t clock,
168 uint32_t lo_threshold,
169 uint32_t hi_threshold) {
170 LOG_INFO(
"Enabling clock count measurement for %s(%d) lo %d hi %d",
171 measure_clock_name(clkmgr, clock), clock, lo_threshold,
173 TRY(dif_clkmgr_enable_measure_counts(clkmgr, clock, lo_threshold,
178status_t clkmgr_testutils_enable_clock_counts_with_expected_thresholds(
179 const dif_clkmgr_t *clkmgr,
bool jitter_enabled,
bool external_clk,
181 static bool counts_initialized =
false;
182 if (!counts_initialized) {
183 TRY(initialize_expected_counts(clkmgr));
184 counts_initialized =
true;
186 TRY_CHECK(!(external_clk && jitter_enabled));
189 TRY(dif_clkmgr_get_dt(clkmgr, &clkmgr_dt));
193 const expected_count_info_t *count_info;
194 if (jitter_enabled) {
195 count_info = &kJitterCountInfos[clk];
196 }
else if (external_clk) {
197#if defined(OPENTITAN_IS_EARLGREY)
210 if (low_speed && dt_actual_clk ==
kDtClockIo) {
213 CHECK(dt_clk_to_meas_clk[dt_actual_clk] <
215 "this clock is not measurable!");
216 count_info = &kNoJitterCountInfos[dt_clk_to_meas_clk[dt_actual_clk]];
217#elif defined(OPENTITAN_IS_DARJEELING)
218 TRY_CHECK(
false,
"Darjeeling has no external clock");
221#error Unsupported top
224 count_info = &kNoJitterCountInfos[clk];
226 TRY(clkmgr_testutils_enable_clock_count(
227 clkmgr, (dif_clkmgr_measure_clock_t)clk,
228 count_info->count - count_info->variability,
229 count_info->count + count_info->variability));
234status_t clkmgr_testutils_check_measurement_enables(
238 dif_clkmgr_measure_clock_t clock = (dif_clkmgr_measure_clock_t)i;
240 TRY(dif_clkmgr_measure_counts_get_enable(clkmgr, clock, &actual_status));
241 if (actual_status != expected_status) {
242 LOG_INFO(
"Unexpected enable for clock %d: expected %s", i,
247 return OK_STATUS(success);
250status_t clkmgr_testutils_disable_clock_counts(
const dif_clkmgr_t *clkmgr) {
251 LOG_INFO(
"Disabling all clock count measurements");
253 dif_clkmgr_measure_clock_t clock = (dif_clkmgr_measure_clock_t)i;
254 TRY(dif_clkmgr_disable_measure_counts(clkmgr, clock));
256 LOG_INFO(
"Disabling all clock count done");
260status_t clkmgr_testutils_check_measurement_counts(
const dif_clkmgr_t *clkmgr) {
261 status_t result = OK_STATUS();
263 TRY(dif_clkmgr_recov_err_code_get_codes(clkmgr, &err_codes));
264 if (err_codes != 0) {
265 LOG_ERROR(
"Unexpected recoverable error codes 0x%x", err_codes);
268 LOG_INFO(
"Clock measurements are okay");
271 TRY(dif_clkmgr_recov_err_code_clear_codes(clkmgr, ~0u));
275status_t clkmgr_testutils_enable_external_clock_blocking(
277 LOG_INFO(
"Configure clkmgr to enable external clock");
278 TRY(dif_clkmgr_external_clock_set_enabled(clkmgr, is_low_speed));
279 TRY(dif_clkmgr_wait_for_ext_clk_switch(clkmgr));
280 LOG_INFO(
"Switching to external clock completes");