blob: 4ea8fbd4b6ab7df8f68524237fa19f166e2016cd [file] [log] [blame]
/*
* Copyright 2023 Google LLC
* Copyright lowRISC contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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;
}