Fix problem with chip_sw_clkmgr_reset_frequency There should be a delay after triggering SW reset so that there is enough time for the SW reset to take effect, and a check after the delay to make sure the reset indeed happened Change-Id: I20076e2691b3da127b651f0b94fb3442ab6a5dbf
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD index ef67744..9e9f935 100644 --- a/sw/device/tests/BUILD +++ b/sw/device/tests/BUILD
@@ -978,10 +978,9 @@ matcha_dv_test( name = "clkmgr_reset_frequency_test", - srcs = ["@lowrisc_opentitan//sw/device/tests:clkmgr_reset_frequency_test.c"], + srcs = [":clkmgr_reset_frequency_test.c"], deps = [ - ":test_dv_lib_opentitan", - "//sw/device/lib/arch:device", + ":test_dv_lib", "//sw/device/lib/testing:clkmgr_testutils", "@lowrisc_opentitan//sw/device/lib/dif:sensor_ctrl", "@lowrisc_opentitan//sw/device/lib/testing:aon_timer_testutils",
diff --git a/sw/device/tests/clkmgr_reset_frequency_test.c b/sw/device/tests/clkmgr_reset_frequency_test.c new file mode 100644 index 0000000..1a574af --- /dev/null +++ b/sw/device/tests/clkmgr_reset_frequency_test.c
@@ -0,0 +1,92 @@ +// Copyright 2023 Google LLC. +// Copyright lowRISC contributors. +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "hw/top_matcha/sw/autogen/top_matcha.h" +#include "sw/device/lib/base/memory.h" +#include "sw/device/lib/dif/dif_sensor_ctrl.h" +#include "sw/device/lib/runtime/log.h" +#include "sw/device/lib/testing/aon_timer_testutils.h" +#include "sw/device/lib/testing/clkmgr_testutils.h" +#include "sw/device/lib/testing/rstmgr_testutils.h" +#include "sw/device/lib/testing/sensor_ctrl_testutils.h" +#include "sw/device/lib/testing/test_framework/check.h" +#include "sw/device/lib/testing/test_framework/ottf_main.h" + +OTTF_DEFINE_TEST_CONFIG(); + +/** + * This test measure clock counts with clkmgr frequency measurements, performing + * 100 measurements per round. Measurement errors (fast or slow clocks) are + * recorded as recoverable error in clkmgr. + * + * This test configures the clock thresholds so it generates errors, after 100 + * measurements it checks that some errors are found, then a reset is triggered, + * and it checks the measurements should be disabled, and no errors should be + * reported. + * + * Notice the test overrides the hardware behavior so it comes out with + * calibrated USB clock, otherwise the USB clock frequency will be incorrect. + * USB calibration should be a separate test, and may be vendor-specific. + */ +const unsigned int kMeasurementsPerRound = 100; + +bool test_main(void) { + dif_clkmgr_t clkmgr; + dif_rstmgr_t rstmgr; + dif_sensor_ctrl_t sensor_ctrl; + + const uint32_t kMeasurementDelayMicros = + aon_timer_testutils_get_us_from_aon_cycles(kMeasurementsPerRound); + + CHECK_DIF_OK(dif_clkmgr_init( + mmio_region_from_addr(TOP_MATCHA_CLKMGR_AON_BASE_ADDR), &clkmgr)); + CHECK_DIF_OK(dif_sensor_ctrl_init( + mmio_region_from_addr(TOP_MATCHA_SENSOR_CTRL_BASE_ADDR), &sensor_ctrl)); + CHECK_DIF_OK(dif_rstmgr_init( + mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr)); + + LOG_INFO("TEST: wait for ast init"); + IBEX_SPIN_FOR(sensor_ctrl_ast_init_done(&sensor_ctrl), + 1000); // Time out at 1000us + LOG_INFO("TEST: done ast init"); + + if (rstmgr_testutils_reset_info_any(&rstmgr, kDifRstmgrResetInfoPor)) { + LOG_INFO("POR reset"); + + // Configure the counters to trigger an error by setting them for external + // clocks. + clkmgr_testutils_enable_clock_counts_with_expected_thresholds( + &clkmgr, /*jitter_enabled=*/false, /*external_clk=*/true, + /*low_speed=*/true); + busy_spin_micros(kMeasurementDelayMicros); + + // Check we get errors, but let the counters keep going. + dif_clkmgr_recov_err_codes_t err_codes; + CHECK_DIF_OK(dif_clkmgr_recov_err_code_get_codes(&clkmgr, &err_codes)); + CHECK(err_codes != 0); + + // Trigger a rstmgr SW reset. + CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr)); + + // Add delay such that the software reset can take effect + busy_spin_micros(100); + + // This should not be reached. + LOG_ERROR("This is unreachable since a reset should have been triggered"); + return false; + } else if (rstmgr_testutils_reset_info_any(&rstmgr, kDifRstmgrResetInfoSw)) { + LOG_INFO("Back from rstmgr SW reset"); + CHECK(clkmgr_testutils_check_measurement_enables(&clkmgr, + kDifToggleDisabled)); + CHECK(clkmgr_testutils_check_measurement_counts(&clkmgr)); + return true; + } else { + dif_rstmgr_reset_info_bitfield_t rst_info; + CHECK_DIF_OK(dif_rstmgr_reset_info_get(&rstmgr, &rst_info)); + LOG_ERROR("Unexpected rst_info 0x%x", rst_info); + return false; + } + return true; +}