Software APIs
dif_sram_ctrl.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 
6 
7 #include "sw/device/lib/base/multibits.h"
8 
9 #include "sram_ctrl_regs.h" // Generated.
10 
11 /**
12  * Obtains the lock state of the "Control" register.
13  *
14  * When locked, new scrambling key and SRAM pseudo-random data overwriting
15  * requests are not available.
16  */
17 static bool sram_ctrl_locked_ctrl(const dif_sram_ctrl_t *sram_ctrl) {
18  return mmio_region_read32(sram_ctrl->base_addr,
19  SRAM_CTRL_CTRL_REGWEN_REG_OFFSET)
20  ? false
21  : true;
22 }
23 
24 /**
25  * Obtains the lock state of the "Exec enable" register.
26  *
27  * When locked, execution from SRAM is disabled, and an attempt to do so
28  * will result in an access violation.
29  */
30 static bool sram_ctrl_exec_locked(const dif_sram_ctrl_t *sram_ctrl) {
31  return mmio_region_read32(sram_ctrl->base_addr,
32  SRAM_CTRL_EXEC_REGWEN_REG_OFFSET)
33  ? false
34  : true;
35 }
36 
37 /**
38  * Locks SRAM Controller "Control" functionality.
39  *
40  * SRAM Scrambling and RAM wiping is no longer available.
41  */
42 static void sram_ctrl_lock_ctrl(const dif_sram_ctrl_t *sram_ctrl) {
43  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REGWEN_REG_OFFSET,
44  0);
45 }
46 
47 /**
48  * Locks SRAM Controller "Execute" functionality.
49  *
50  * Execution from SRAM cannot be changed (when enabled - it stays enabled, and
51  * vice versa).
52  */
53 static void sram_ctrl_lock_exec(const dif_sram_ctrl_t *sram_ctrl) {
54  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_EXEC_REGWEN_REG_OFFSET,
55  0);
56 }
57 
58 /**
59  * Obtains the SRAM Controller statues.
60  *
61  * `dif_sram_ctrl_status_t` can be used to query individual flags.
62  */
63 static uint32_t sram_ctrl_get_status(const dif_sram_ctrl_t *sram_ctrl) {
64  return mmio_region_read32(sram_ctrl->base_addr, SRAM_CTRL_STATUS_REG_OFFSET);
65 }
66 
68  if (sram_ctrl == NULL) {
69  return kDifBadArg;
70  }
71 
72  if (sram_ctrl_locked_ctrl(sram_ctrl)) {
73  return kDifLocked;
74  }
75 
76  // Issue request for new scrambling key.
77  uint32_t reg =
78  bitfield_bit32_write(0, SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, true);
79  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
80 
81  // Wait until the scrambling key has been updated.
83  do {
84  status = sram_ctrl_get_status(sram_ctrl);
85  } while ((status & kDifSramCtrlStatusScrKeyValid) == 0);
86 
87  // Overwrite memory with pseudo random data.
88  reg = bitfield_bit32_write(0, SRAM_CTRL_CTRL_INIT_BIT, true);
89  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
90 
91  // Wait for memory to be overwritten with pseudo random data.
92  do {
93  status = sram_ctrl_get_status(sram_ctrl);
94  } while ((status & kDifSramCtrlStatusInitDone) == 0);
95 
96  // Check for the errors during memory overwriting.
98 }
99 
101  if (sram_ctrl == NULL) {
102  return kDifBadArg;
103  }
104 
105  if (sram_ctrl_locked_ctrl(sram_ctrl)) {
106  return kDifLocked;
107  }
108 
109  uint32_t reg =
110  bitfield_bit32_write(0, SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, true);
111  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
112 
113  return kDifOk;
114 }
115 
117  if (sram_ctrl == NULL) {
118  return kDifBadArg;
119  }
120 
121  if (sram_ctrl_locked_ctrl(sram_ctrl)) {
122  return kDifLocked;
123  }
124 
125  uint32_t reg = bitfield_bit32_write(0, SRAM_CTRL_CTRL_INIT_BIT, true);
126  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
127 
128  return kDifOk;
129 }
130 
133  if (sram_ctrl == NULL) {
134  return kDifBadArg;
135  }
136 
137  if (status == NULL) {
138  return kDifBadArg;
139  }
140 
141  *status = sram_ctrl_get_status(sram_ctrl);
142 
143  return kDifOk;
144 }
145 
147  dif_toggle_t *state) {
148  if (sram_ctrl == NULL || state == NULL) {
149  return kDifBadArg;
150  }
151 
152  uint32_t reg =
153  mmio_region_read32(sram_ctrl->base_addr, SRAM_CTRL_EXEC_REG_OFFSET);
154 
155  *state = (reg == kMultiBitBool4True) ? kDifToggleEnabled : kDifToggleDisabled;
156 
157  return kDifOk;
158 }
159 
161  dif_toggle_t state) {
162  if (sram_ctrl == NULL) {
163  return kDifBadArg;
164  }
165 
166  if (sram_ctrl_exec_locked(sram_ctrl)) {
167  return kDifLocked;
168  }
169 
170  uint32_t value =
171  (state == kDifToggleEnabled) ? kMultiBitBool4True : kMultiBitBool4False;
172  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_EXEC_REG_OFFSET, value);
173 
174  return kDifOk;
175 }
176 
178  dif_sram_ctrl_lock_t lock) {
179  if (sram_ctrl == NULL) {
180  return kDifBadArg;
181  }
182 
183  switch (lock) {
185  sram_ctrl_lock_ctrl(sram_ctrl);
186  break;
188  sram_ctrl_lock_exec(sram_ctrl);
189  break;
190  default:
191  return kDifError;
192  }
193 
194  return kDifOk;
195 }
196 
199  bool *is_locked) {
200  if (sram_ctrl == NULL || is_locked == NULL) {
201  return kDifBadArg;
202  }
203 
204  switch (lock) {
206  *is_locked = sram_ctrl_locked_ctrl(sram_ctrl);
207  break;
209  *is_locked = sram_ctrl_exec_locked(sram_ctrl);
210  break;
211  default:
212  return kDifError;
213  }
214 
215  return kDifOk;
216 }
217 
219  multi_bit_bool_t *success,
220  multi_bit_bool_t clear) {
221  if (sram_ctrl == NULL || success == NULL) {
222  return kDifBadArg;
223  }
224 
225  // We do not use any control flow statements to determine whether to clear
226  // the CSR or not. Rather, the register is always written and we let the
227  // MuBi logic determine what needs to be done. I.e., the register is
228  // specified as W1C in which case a clear operation only takes place if
229  // clear is set to kMultiBitBool4True. If it is set to kMultiBitBool4False,
230  // the current state will persist.
231  *success = mmio_region_read32(sram_ctrl->base_addr,
232  SRAM_CTRL_SCR_KEY_ROTATED_REG_OFFSET);
233  mmio_region_write32(sram_ctrl->base_addr,
234  SRAM_CTRL_SCR_KEY_ROTATED_REG_OFFSET, clear);
235 
236  return kDifOk;
237 }