Software APIs
sram_ctrl_testutils.c
1// Copyright lowRISC contributors (OpenTitan project).
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4
5#include "sw/device/lib/testing/sram_ctrl_testutils.h"
6
11#include "sw/device/lib/testing/test_framework/check.h"
12
13#define MODULE_ID MAKE_MODULE_ID('s', 'c', 't')
14
15void sram_ctrl_testutils_write(uintptr_t address,
16 const sram_ctrl_testutils_data_t data) {
17 mmio_region_t region = mmio_region_from_addr(address);
18 for (size_t index = 0; index < data.len; ++index) {
19 ptrdiff_t offset = (ptrdiff_t)(sizeof(uint32_t)) * (ptrdiff_t)index;
20 mmio_region_write32(region, offset, data.words[index]);
21 }
22}
23
24/**
25 * Checks whether the SRAM operation has finished.
26 */
27static bool check_finished(const dif_sram_ctrl_t *sram_ctrl,
30 dif_result_t res = dif_sram_ctrl_get_status(sram_ctrl, &status);
31 return (res == kDifOk) && (status & flag);
32}
33
34status_t sram_ctrl_testutils_scramble(const dif_sram_ctrl_t *sram_ctrl) {
35 TRY(dif_sram_ctrl_request_new_key(sram_ctrl));
36
37 // Calculate the timeout time.
38 // The SRAM Controller documentation says that it takes approximately 800
39 // cycles to perform the SRAM scrambling operation (50 cycles were added to
40 // this number to be on a safe side).
41 //
42 // The calculation is equivalent of (1us / clk) * 850 (clock period expressed
43 // in micro seconds multiplied by number of cycles needed to perform
44 // the RAM scrambling operation).
45 //
46 // Expressing this calculation in 1us / (clk / 850) is less intuitive, but
47 // makes more sense when dealing with the integer division, as when the clock
48 // frequency is greater than 1 million hertz, the first expression will give
49 // inaccurate results due to clock period being zero. It should not be a
50 // problem with the second version, as clock frequency won't be less than
51 // 850. We add 1 microsecond to account for flooring.
52 uint32_t usec = (uint32_t)udiv64_slow(
53 1000000, udiv64_slow(kClockFreqCpuHz, 850, NULL) + 1, NULL);
54
55 // Loop until new scrambling key has been obtained.
56 LOG_INFO("Waiting for SRAM scrambling to finish");
57 IBEX_TRY_SPIN_FOR(check_finished(sram_ctrl, kDifSramCtrlStatusScrKeyValid),
58 usec);
59 return OK_STATUS();
60}
61
62status_t sram_ctrl_testutils_wipe(const dif_sram_ctrl_t *sram_ctrl) {
63 CHECK_DIF_OK(dif_sram_ctrl_wipe(sram_ctrl));
64 // The timeout calculation is the same as the scramble timeout.
65 uint32_t usec = (uint32_t)udiv64_slow(
66 1000000, udiv64_slow(kClockFreqCpuHz, 850, NULL) + 1, NULL);
67 LOG_INFO("Waiting for SRAM wipe to finish");
68 IBEX_SPIN_FOR(check_finished(sram_ctrl, kDifSramCtrlStatusInitDone), usec);
69 return OK_STATUS();
70}