Software APIs
sram_ctrl_readback_test.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 //! This test is identical to the sram_ctrl_memset_test except that the SRAM
6 //! readack mode gets enabled.
7 
13 #include "sw/device/lib/testing/test_framework/check.h"
15 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
16 
18 #include "sram_ctrl_regs.h" // Generated.
19 
20 // Define some amount of data we should leave in SRAM to check it gets wiped.
21 enum {
22  kSramCtrlTestDataSizeWords = 16,
23 };
24 
25 OTTF_DEFINE_TEST_CONFIG();
26 
27 static const uint32_t kStatusRegMask = kDifSramCtrlStatusBusIntegErr |
30 
31 static const uint32_t kRandomData[kSramCtrlTestDataSizeWords] = {
32  0x6b4abfae, 0x63bdb6e7, 0x87f99b1a, 0xa214dffe, 0xb12291f9, 0xd0cd1abe,
33  0x5c95e716, 0xe887aab1, 0x307f6ef9, 0x6f5c0464, 0x5882279d, 0x44c19574,
34  0x1bd20079, 0xf8250ead, 0x4bf362a4, 0xad41437d};
35 
36 /// Write `kRandomData` to an SRAM region.
37 static void write_data(mmio_region_t sram_region) {
38  for (int i = 0; i < kSramCtrlTestDataSizeWords; ++i) {
39  mmio_region_write32(sram_region, i * (ptrdiff_t)sizeof(uint32_t),
40  kRandomData[i]);
41  }
42 }
43 
44 /// Check that the contents of an SRAM region match `kRandomData`.
45 ///
46 /// The `matches` arg is used to specify whether you expect the SRAM region to
47 /// match `kRandomData`, or whether it should have been re-scrambled and no
48 /// longer match.
49 static void check_data_matches(mmio_region_t sram_region, bool matches) {
50  for (int i = 0; i < kSramCtrlTestDataSizeWords; ++i) {
51  uint32_t word =
52  mmio_region_read32(sram_region, i * (ptrdiff_t)sizeof(uint32_t));
53 
54  if (matches) {
55  CHECK(word == kRandomData[i],
56  "Data at index %u mismached, expected: %04x, got: %04x", i,
57  kRandomData[i], word);
58  } else if (word != kRandomData[i]) {
59  return;
60  }
61  }
62 
63  // If we got to this point and expected _not_ to match, fail.
64  CHECK(matches, "Data in SRAM was not rescrambled correctly");
65 }
66 
67 /// (Re-)initialize an SRAM region with pseudorandom data.
68 static void init_sram(dif_sram_ctrl_t sram_ctrl) {
69  uint32_t init = bitfield_bit32_write(0, SRAM_CTRL_CTRL_INIT_BIT, true);
70  mmio_region_write32(sram_ctrl.base_addr, SRAM_CTRL_CTRL_REG_OFFSET, init);
71 
72  // Spin until SRAM_CTRL is ready.
74  do {
75  CHECK_DIF_OK(dif_sram_ctrl_get_status(&sram_ctrl, &status));
76  } while ((status & kDifSramCtrlStatusInitDone) == 0x0);
77 
78  CHECK((status & kStatusRegMask) == 0x0,
79  "SRAM ret status error bits set, status = %08x.", status);
80 }
81 
82 bool test_main(void) {
83  // Initialize SRAM_CTRL hardware.
84  dif_sram_ctrl_t sram_ctrl_ret;
85  CHECK_DIF_OK(dif_sram_ctrl_init(
87  &sram_ctrl_ret));
88 
89  init_sram(sram_ctrl_ret);
90 
91  uintptr_t sram_ret_buffer_addr =
93  offsetof(retention_sram_t, owner);
94 
95  mmio_region_t sram_region_ret_addr =
96  mmio_region_from_addr(sram_ret_buffer_addr);
97 
98  // Enable the SRAM readback mode for the first test round.
99  CHECK_DIF_OK(dif_sram_ctrl_readback_set(&sram_ctrl_ret, kDifToggleEnabled));
100  for (size_t it = 0; it < 2; it++) {
101  // Write some data to retention SRAM and read it back to validate.
102  write_data(sram_region_ret_addr);
103  // Read back the data to validate it was written.
104  check_data_matches(sram_region_ret_addr, true);
105  // Redo test with SRAM readback mode disabled.
106  CHECK_DIF_OK(
108  }
109 
110  // Lock readback enable feature.
111  CHECK_DIF_OK(dif_sram_ctrl_lock(&sram_ctrl_ret, kDifSramCtrlLockReadback));
112 
113  // Check if lock works.
114  CHECK(kDifLocked ==
116  "Readback feature not locked.");
117 
118  // Run initialization on the retention SRAM and check that the data is gone.
119  init_sram(sram_ctrl_ret);
120  check_data_matches(sram_region_ret_addr, false);
121 
122  return true;
123 }