Software APIs
sram_ctrl_subword_access_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 
10 #include "sw/device/lib/testing/test_framework/check.h"
12 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
13 
15 
16 enum {
17  kSramCtrlTestDataSizeWords = 3,
18  kSramCtrlTestDataSizeBytes = kSramCtrlTestDataSizeWords * 4,
19 };
20 
21 OTTF_DEFINE_TEST_CONFIG();
22 
23 static const uint32_t kStatusRegMask = kDifSramCtrlStatusBusIntegErr |
26 
27 static const uint32_t kRandomData[kSramCtrlTestDataSizeWords] = {
28  0x6b4abfae, 0x63bdb6e7, 0x87f99b1a};
29 
30 // Buffer to allow the compiler to allocate a safe area in Main SRAM where
31 // we can do the write/read test without the risk of clobbering data
32 // used by the program.
33 OT_SECTION(".data")
34 static volatile uint32_t sram_main_buffer[kSramCtrlTestDataSizeWords];
35 
36 /// Write `kRandomData` to SRAM, then read back a u8, u16, u32, and u64 from
37 /// each possible byte offset.
38 static void read_subwords_check(mmio_region_t region) {
39  mmio_region_memcpy_to_mmio32(region, 0, kRandomData,
40  kSramCtrlTestDataSizeBytes);
41 
42  // Check byte reads.
43  for (uint32_t i = 0; i < kSramCtrlTestDataSizeBytes; ++i) {
44  uint8_t expected = ((volatile uint8_t *)kRandomData)[i];
45  uint8_t got = ((volatile uint8_t *)region.base)[i];
46  CHECK(expected == got,
47  "byte %d read back incorrectly: expected %02x, got %02x", i, expected,
48  got);
49  }
50 
51  // Check uint16_t reads.
52  for (uint32_t i = 0; i < kSramCtrlTestDataSizeBytes - 1; ++i) {
53  uint16_t expected = *(volatile uint16_t *)((uint8_t *)kRandomData + i);
54  uint16_t got = *(volatile uint16_t *)((uint8_t *)region.base + i);
55  CHECK(expected == got,
56  "uint16_t %d read back incorrectly: expected %04x, got %04x", i,
57  expected, got);
58  }
59 
60  // Check uint32_t reads.
61  for (uint32_t i = 0; i < kSramCtrlTestDataSizeBytes - 3; ++i) {
62  uint32_t expected = *(volatile uint32_t *)((uint8_t *)kRandomData + i);
63  uint32_t got = *(volatile uint32_t *)((uint8_t *)region.base + i);
64  CHECK(expected == got,
65  "uint32_t %d read back incorrectly: expected %08x, got %08x", i,
66  expected, got);
67  }
68 
69  // Check uint64_t reads.
70  for (uint32_t i = 0; i < kSramCtrlTestDataSizeBytes - 7; ++i) {
71  uint64_t expected = *(volatile uint64_t *)((uint8_t *)kRandomData + i);
72  uint64_t got = *(volatile uint64_t *)((uint8_t *)region.base + i);
73  CHECK(expected == got,
74  "uint64_t %d read back incorrectly: expected %08x%08x, got %08x%08x",
75  i, (uint32_t)(expected >> 32), (uint32_t)expected,
76  (uint32_t)(got >> 32), (uint32_t)got);
77  }
78 }
79 
80 /// Clear a whole SRAM region.
81 static void clear_sram_region(mmio_region_t region) {
82  for (uint32_t i = 0; i < kSramCtrlTestDataSizeWords; ++i) {
83  mmio_region_write32(region, (ptrdiff_t)i, 0);
84  }
85 }
86 
87 /// Check that the contents of an SRAM region match the bytes of `kRandomData`
88 /// at a given byte offset and byte length.
89 static void check_sram_contents(mmio_region_t region, uint32_t offset,
90  uint32_t len) {
91  for (uint32_t i = 0; i < len; ++i) {
92  uint8_t expected = ((uint8_t *)kRandomData)[offset + i];
93  uint8_t got = mmio_region_read8(region, (ptrdiff_t)(offset + i));
94  CHECK(expected == got, "byte %d did not match: expected %02x, got %02x",
95  offset + i, expected, got);
96  }
97 }
98 
99 /// Write each of a u8, u16, u32, and u64 from to every possible byte offset in
100 /// SRAM, reading them back to check the writes.
101 static void write_subwords_check(mmio_region_t region) {
102  // Check byte writes.
103  for (uint32_t i = 0; i < kSramCtrlTestDataSizeBytes; ++i) {
104  clear_sram_region(region);
105  ((volatile uint8_t *)region.base)[i] = ((uint8_t *)kRandomData)[i];
106  check_sram_contents(region, i, 1);
107  }
108 
109  // Check uint16_t writes.
110  for (uint32_t i = 0; i < kSramCtrlTestDataSizeBytes - 1; ++i) {
111  clear_sram_region(region);
112  *(volatile uint16_t *)((uint8_t *)region.base + i) =
113  *(uint16_t *)((uint8_t *)kRandomData + i);
114  check_sram_contents(region, i, 2);
115  }
116 
117  // Check uint32_t writes.
118  for (uint32_t i = 0; i < kSramCtrlTestDataSizeBytes - 3; ++i) {
119  clear_sram_region(region);
120  *(volatile uint32_t *)((uint8_t *)region.base + i) =
121  *(uint32_t *)((uint8_t *)kRandomData + i);
122  check_sram_contents(region, i, 4);
123  }
124 
125  // Check uint64_t writes.
126  for (uint32_t i = 0; i < kSramCtrlTestDataSizeBytes - 7; ++i) {
127  clear_sram_region(region);
128  *(volatile uint64_t *)((uint8_t *)region.base + i) =
129  *(uint64_t *)((uint8_t *)kRandomData + i);
130  check_sram_contents(region, i, 8);
131  }
132 }
133 
134 bool test_main(void) {
135  // Initialize SRAM_CTRL hardware.
136  dif_sram_ctrl_t sram_ctrl_main;
137  dif_sram_ctrl_t sram_ctrl_ret;
138  CHECK_DIF_OK(dif_sram_ctrl_init(
140  &sram_ctrl_main));
141  CHECK_DIF_OK(dif_sram_ctrl_init(
143  &sram_ctrl_ret));
144 
147 
148  // Check Status registers.
149  CHECK_DIF_OK(dif_sram_ctrl_get_status(&sram_ctrl_ret, &status_ret));
150  CHECK_DIF_OK(dif_sram_ctrl_get_status(&sram_ctrl_main, &status_main));
151 
152  CHECK((status_main & kStatusRegMask) == 0x0,
153  "SRAM main status error bits set, status = %08x.", status_main);
154  CHECK((status_ret & kStatusRegMask) == 0x0,
155  "SRAM ret status error bits set, status = %08x.", status_ret);
156 
157  // Read and Write to/from SRAMs. Main SRAM will use the address of the
158  // buffer that has been allocated.
159  uintptr_t sram_main_buffer_addr = (uintptr_t)&sram_main_buffer;
160  // Ret SRAM will start at the beginning of the owner section, allowing this
161  // test to run on silicon where creator SRAM is in use.
162  uintptr_t sram_ret_buffer_addr =
164  offsetof(retention_sram_t, owner);
165 
166  mmio_region_t sram_region_main_addr =
167  mmio_region_from_addr(sram_main_buffer_addr);
168  mmio_region_t sram_region_ret_base_addr =
169  mmio_region_from_addr(sram_ret_buffer_addr);
170 
171  // Subword read checks.
172  LOG_INFO("Checking subword reads on SRAM_RET");
173  read_subwords_check(sram_region_ret_base_addr);
174  LOG_INFO("Checking subword reads on SRAM_MAIN");
175  read_subwords_check(sram_region_main_addr);
176 
177  // Subword write checks.
178  LOG_INFO("Checking subword writes on SRAM_RET");
179  write_subwords_check(sram_region_ret_base_addr);
180  LOG_INFO("Checking subword writes on SRAM_MAIN");
181  write_subwords_check(sram_region_main_addr);
182 
183  return true;
184 }