Software APIs
sram_ctrl_smoketest.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 "dt/dt_sram_ctrl.h"
11 #include "sw/device/lib/testing/test_framework/check.h"
13 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
14 
15 // Define a number of reads and writes to perform; for our purposes a small
16 // number will be sufficient.
17 #define SRAM_CTRL_TEST_DATA_SIZE_WORDS 16
18 
19 static_assert(kDtSramCtrlCount >= 1,
20  "This test requires at least one RAM Control instance");
21 static_assert(kDtSramCtrlCount < 100,
22  "The reported SRAM_CTRL instance number may be incorrect");
23 
24 #define SRAM_CTRL_NAME(x) #x
25 
26 OTTF_DEFINE_TEST_CONFIG();
27 
28 static const uint32_t kStatusRegMask = kDifSramCtrlStatusBusIntegErr |
31 
32 static const uint32_t kRandomData[SRAM_CTRL_TEST_DATA_SIZE_WORDS] = {
33  0x6b4abfae, 0x63bdb6e7, 0x87f99b1a, 0xa214dffe, 0xb12291f9, 0xd0cd1abe,
34  0x5c95e716, 0xe887aab1, 0x307f6ef9, 0x6f5c0464, 0x5882279d, 0x44c19574,
35  0x1bd20079, 0xf8250ead, 0x4bf362a4, 0xad41437d};
36 
37 // Properties of each of the SRAM_CTRL blocks to be tested.
38 static struct {
39  /**
40  * Interface to SRAM_CTRL.
41  */
42  dif_sram_ctrl_t dif;
43  /**
44  * Base address of test buffer within SRAM_CTRL instance.
45  */
46  uintptr_t buf;
47  /**
48  * MMIO access to test buffer.
49  */
50  mmio_region_t region;
51  /**
52  * Name of SRAM_CTRL instance.
53  */
54  const char *name;
55  /**
56  * Name buffer, for those instances which are identified numerically.
57  */
58  char nameBuf[12];
59 } sram_ctrl[kDtSramCtrlCount];
60 
61 // Buffer to allow the compiler to allocate a safe area in Main SRAM where
62 // we can do the write/read test without the risk of clobbering data
63 // used by the program.
64 OT_SECTION(".data")
65 static volatile uint32_t sram_main_buffer[SRAM_CTRL_TEST_DATA_SIZE_WORDS];
66 
67 // Write and read small chunks of data to each SRAM_CTRL to test basic
68 // functionality; exercise all of the controllers in an interleaved fashion
69 // just to increase the chance of catching any crosstalk issues/interactions
70 // between the instances.
71 static void write_read_check(void) {
72  for (int i = 0; i < SRAM_CTRL_TEST_DATA_SIZE_WORDS; ++i) {
73  for (dt_sram_ctrl_t sc = (dt_sram_ctrl_t)0; sc < kDtSramCtrlCount; ++sc) {
74  mmio_region_write32(sram_ctrl[sc].region, i * (ptrdiff_t)sizeof(uint32_t),
75  kRandomData[i]);
76  uint32_t rw_data_32 = mmio_region_read32(sram_ctrl[sc].region,
77  i * (ptrdiff_t)sizeof(uint32_t));
78  CHECK(rw_data_32 == kRandomData[i],
79  "Memory Write/Read Mismatch for %s, index %d, data read = %08x "
80  "data_expected = %08x.",
81  sram_ctrl[sc].name, i, rw_data_32, kRandomData[i]);
82  }
83  }
84 }
85 
86 bool test_main(void) {
87  // Initialize SRAM_CTRL blocks.
88  for (dt_sram_ctrl_t sc = (dt_sram_ctrl_t)0; sc < kDtSramCtrlCount; ++sc) {
89  CHECK_DIF_OK(dif_sram_ctrl_init_from_dt(sc, &sram_ctrl[sc].dif));
90 
91  // Decide upon the buffer address to be used for this SRAM controller.
92  switch (sc) {
93  // Main SRAM will use the address of the buffer that has been allocated.
94  case kDtSramCtrlMain:
95  sram_ctrl[sc].buf = (uintptr_t)sram_main_buffer;
96  sram_ctrl[sc].name = SRAM_CTRL_NAME(kDtSramCtrlMain);
97  break;
98 
99  default:
100  // Ret SRAM can start at the beginning of the owner section.
101  sram_ctrl[sc].buf =
102  (uintptr_t)dt_sram_ctrl_reg_block(sc, kDtSramCtrlRegBlockRam);
103  // Assume that no target device has more than 100 SRAM_CTRL instances.
104  unsigned dig = (unsigned)sc / 10;
105  sram_ctrl[sc].nameBuf[0] = (char)('0' + dig);
106  sram_ctrl[sc].nameBuf[1] = (char)('0' + ((unsigned)sc - dig * 10));
107  sram_ctrl[sc].name = sram_ctrl[sc].nameBuf;
108  break;
109  }
110  // Obtain access to the buffer.
111  sram_ctrl[sc].region = mmio_region_from_addr(sram_ctrl[sc].buf);
112  }
113 
114  // Check Status registers
115  for (dt_sram_ctrl_t sc = (dt_sram_ctrl_t)0; sc < kDtSramCtrlCount; ++sc) {
117  CHECK_DIF_OK(dif_sram_ctrl_get_status(&sram_ctrl[sc].dif, &status));
118  CHECK((status & kStatusRegMask) == 0x0,
119  "SRAM %s status error bits set, status = %08x.", sram_ctrl[sc].name,
120  status);
121  }
122 
123  // Write/read to/from SRAMs.
124  write_read_check();
125 
126  return true;
127 }