| // Copyright lowRISC contributors. | |
| // Licensed under the Apache License, Version 2.0, see LICENSE for details. | |
| // SPDX-License-Identifier: Apache-2.0 | |
| #include "sw/device/lib/testing/otp_ctrl_testutils.h" | |
| #include "sw/device/lib/dif/dif_otp_ctrl.h" | |
| #include "sw/device/lib/runtime/ibex.h" | |
| #include "sw/device/lib/runtime/log.h" | |
| #include "sw/device/lib/testing/test_framework/check.h" | |
| /* | |
| * OTP the Direct Access Interface (DAI) operation time-out in micro seconds. | |
| * | |
| * It is not possible to predict the specific cycle count that a DAI operation | |
| * takes, thus arbitrary value of 100us is used. | |
| */ | |
| const uint8_t kOtpDaiTimeoutUs = 100; | |
| /** | |
| * Checks whether the DAI operation has finished. | |
| */ | |
| static bool dai_finished(const dif_otp_ctrl_t *otp_ctrl) { | |
| dif_otp_ctrl_status_t status; | |
| CHECK_DIF_OK(dif_otp_ctrl_get_status(otp_ctrl, &status)); | |
| return bitfield_bit32_read(status.codes, kDifOtpCtrlStatusCodeDaiIdle); | |
| } | |
| void otp_ctrl_testutils_dai_access_error_check(const dif_otp_ctrl_t *otp_ctrl, | |
| exp_test_result_t exp_result, | |
| int32_t address) { | |
| dif_otp_ctrl_status_t status; | |
| CHECK_DIF_OK(dif_otp_ctrl_get_status(otp_ctrl, &status)); | |
| if (exp_result == kExpectFailed) { | |
| if (!bitfield_bit32_read(status.codes, kDifOtpCtrlStatusCodeDaiError)) { | |
| LOG_ERROR("Expected a DAI error for access to 0x%x", address); | |
| } | |
| if (status.causes[kDifOtpCtrlStatusCodeDaiError] != | |
| kDifOtpCtrlErrorLockedAccess) { | |
| LOG_ERROR("Expected access locked error for access to 0x%x", address); | |
| } | |
| } else { | |
| if (bitfield_bit32_read(status.codes, kDifOtpCtrlStatusCodeDaiError)) { | |
| LOG_ERROR("No DAI error expected for access to 0x%x", address); | |
| } | |
| if (status.causes[kDifOtpCtrlStatusCodeDaiError] != kDifOtpCtrlErrorOk) { | |
| LOG_ERROR("No DAI error code expected for access to 0x%x", address); | |
| } | |
| } | |
| } | |
| void otp_ctrl_testutils_wait_for_dai(const dif_otp_ctrl_t *otp_ctrl) { | |
| IBEX_SPIN_FOR(dai_finished(otp_ctrl), kOtpDaiTimeoutUs); | |
| } | |
| void otp_ctrl_testutils_lock_partition(const dif_otp_ctrl_t *otp, | |
| dif_otp_ctrl_partition_t partition, | |
| uint64_t digest) { | |
| CHECK_DIF_OK(dif_otp_ctrl_dai_digest(otp, partition, digest)); | |
| otp_ctrl_testutils_wait_for_dai(otp); | |
| } |