blob: 0fb5a473d5fa27bf7f52c1685f874ece7726ba9f [file] [log] [blame]
// 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/sram_ctrl_testutils.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_sram_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"
void sram_ctrl_testutils_write(uintptr_t address,
const sram_ctrl_testutils_data_t data) {
mmio_region_t region = mmio_region_from_addr(address);
for (size_t index = 0; index < data.len; ++index) {
mmio_region_write32(region, sizeof(uint32_t) * index, data.words[index]);
}
}
/**
* Checks whether the SRAM scramble operation has finished.
*/
static bool scramble_finished(const dif_sram_ctrl_t *sram_ctrl) {
dif_sram_ctrl_status_bitfield_t status;
CHECK_DIF_OK(dif_sram_ctrl_get_status(sram_ctrl, &status));
return status & kDifSramCtrlStatusScrKeyValid;
}
void sram_ctrl_testutils_scramble(const dif_sram_ctrl_t *sram_ctrl) {
CHECK_DIF_OK(dif_sram_ctrl_request_new_key(sram_ctrl));
// Calculate the timeout time.
// The SRAM Controller documentation says that it takes approximately 800
// cycles to perform the SRAM scrambling operation (50 cycles were added to
// this number to be on a safe side).
//
// The calculation is equivalent of (1us / clk) * 850 (clock period expressed
// in micro seconds multiplied by number of cycles needed to perform
// the RAM scrambling operation).
//
// Expressing this calculation in 1us / (clk / 850) is less intuitive, but
// makes more sense when dealing with the integer division, as when the clock
// frequency is greater than 1 million hertz, the first expression will give
// inaccurate results due to clock period being zero. It should not be a
// problem with the second version, as clock frequency won't be less than
// 850. We add 1 microsecond to account for flooring.
uint32_t usec =
udiv64_slow(1000000, udiv64_slow(kClockFreqCpuHz, 850, NULL) + 1, NULL);
// Loop until new scrambling key has been obtained.
LOG_INFO("Waiting for SRAM scrambling to finish");
IBEX_SPIN_FOR(scramble_finished(sram_ctrl), usec);
}
/**
* Checks whether the SRAM wipe operation has finished.
*/
static bool wipe_finished(const dif_sram_ctrl_t *sram_ctrl) {
dif_sram_ctrl_status_bitfield_t status;
CHECK_DIF_OK(dif_sram_ctrl_get_status(sram_ctrl, &status));
return status & kDifSramCtrlStatusInitDone;
}
void sram_ctrl_testutils_wipe(const dif_sram_ctrl_t *sram_ctrl) {
CHECK_DIF_OK(dif_sram_ctrl_wipe(sram_ctrl));
// The timeout calculation is the same as the scramble timeout.
uint32_t usec =
udiv64_slow(1000000, udiv64_slow(kClockFreqCpuHz, 850, NULL) + 1, NULL);
LOG_INFO("Waiting for SRAM wipe to finish");
IBEX_SPIN_FOR(wipe_finished(sram_ctrl), usec);
}
void sram_ctrl_testutils_check_backdoor_write(uintptr_t backdoor_addr,
uint32_t num_words,
uint32_t offset_addr,
const uint8_t *expected_bytes) {
mmio_region_t mem_region = mmio_region_from_addr(backdoor_addr);
uint32_t backdoor_data[num_words];
uint32_t expected_data[num_words];
for (int i = 0; i < num_words; ++i) {
backdoor_data[i] =
mmio_region_read32(mem_region, sizeof(uint32_t) * (offset_addr + i));
// The expected data bytes are organized little-endian.
expected_data[i] = expected_bytes[(i * sizeof(uint32_t)) + 3] << 24 |
expected_bytes[(i * sizeof(uint32_t)) + 2] << 16 |
expected_bytes[(i * sizeof(uint32_t)) + 1] << 8 |
expected_bytes[(i * sizeof(uint32_t))];
CHECK(backdoor_data[i] == expected_data[i]);
}
}