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 
15 void 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  */
27 static 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 
34 status_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 
62 status_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 }