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  * Obtains the lock state of the "Readback enable" register.
39  *
40  * When locked, enabling or disabling the readback feature is not possible.
41  */
42 static bool sram_ctrl_readback_locked(const dif_sram_ctrl_t *sram_ctrl) {
43  return mmio_region_read32(sram_ctrl->base_addr,
44  SRAM_CTRL_READBACK_REGWEN_REG_OFFSET)
45  ? false
46  : true;
47 }
48 
49 /**
50  * Locks SRAM Controller "Control" functionality.
51  *
52  * SRAM Scrambling and RAM wiping is no longer available.
53  */
54 static void sram_ctrl_lock_ctrl(const dif_sram_ctrl_t *sram_ctrl) {
55  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REGWEN_REG_OFFSET,
56  0);
57 }
58 
59 /**
60  * Locks SRAM Controller "Execute" functionality.
61  *
62  * Execution from SRAM cannot be changed (when enabled - it stays enabled, and
63  * vice versa).
64  */
65 static void sram_ctrl_lock_exec(const dif_sram_ctrl_t *sram_ctrl) {
66  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_EXEC_REGWEN_REG_OFFSET,
67  0);
68 }
69 
70 /**
71  * Locks SRAM Controller "Readback" functionality.
72  *
73  * Enabling / disabling the readback functionality is no longer available.
74  */
75 static void sram_ctrl_lock_readback(const dif_sram_ctrl_t *sram_ctrl) {
76  mmio_region_write32(sram_ctrl->base_addr,
77  SRAM_CTRL_READBACK_REGWEN_REG_OFFSET, 0);
78 }
79 
80 /**
81  * Obtains the SRAM Controller statues.
82  *
83  * `dif_sram_ctrl_status_t` can be used to query individual flags.
84  */
85 static uint32_t sram_ctrl_get_status(const dif_sram_ctrl_t *sram_ctrl) {
86  return mmio_region_read32(sram_ctrl->base_addr, SRAM_CTRL_STATUS_REG_OFFSET);
87 }
88 
90  if (sram_ctrl == NULL) {
91  return kDifBadArg;
92  }
93 
94  if (sram_ctrl_locked_ctrl(sram_ctrl)) {
95  return kDifLocked;
96  }
97 
98  // Issue request for new scrambling key.
99  uint32_t reg =
100  bitfield_bit32_write(0, SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, true);
101  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
102 
103  // Wait until the scrambling key has been updated.
105  do {
106  status = sram_ctrl_get_status(sram_ctrl);
107  } while ((status & kDifSramCtrlStatusScrKeyValid) == 0);
108 
109  // Overwrite memory with pseudo random data.
110  reg = bitfield_bit32_write(0, SRAM_CTRL_CTRL_INIT_BIT, true);
111  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
112 
113  // Wait for memory to be overwritten with pseudo random data.
114  do {
115  status = sram_ctrl_get_status(sram_ctrl);
116  } while ((status & kDifSramCtrlStatusInitDone) == 0);
117 
118  // Check for the errors during memory overwriting.
119  return (status & kDifSramCtrlStatusInitErr) == 0 ? kDifOk : kDifError;
120 }
121 
123  if (sram_ctrl == NULL) {
124  return kDifBadArg;
125  }
126 
127  if (sram_ctrl_locked_ctrl(sram_ctrl)) {
128  return kDifLocked;
129  }
130 
131  uint32_t reg =
132  bitfield_bit32_write(0, SRAM_CTRL_CTRL_RENEW_SCR_KEY_BIT, true);
133  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
134 
135  return kDifOk;
136 }
137 
139  if (sram_ctrl == NULL) {
140  return kDifBadArg;
141  }
142 
143  if (sram_ctrl_locked_ctrl(sram_ctrl)) {
144  return kDifLocked;
145  }
146 
147  uint32_t reg = bitfield_bit32_write(0, SRAM_CTRL_CTRL_INIT_BIT, true);
148  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_CTRL_REG_OFFSET, reg);
149 
150  return kDifOk;
151 }
152 
155  if (sram_ctrl == NULL) {
156  return kDifBadArg;
157  }
158 
159  if (status == NULL) {
160  return kDifBadArg;
161  }
162 
163  *status = sram_ctrl_get_status(sram_ctrl);
164 
165  return kDifOk;
166 }
167 
169  dif_toggle_t *state) {
170  if (sram_ctrl == NULL || state == NULL) {
171  return kDifBadArg;
172  }
173 
174  uint32_t reg =
175  mmio_region_read32(sram_ctrl->base_addr, SRAM_CTRL_EXEC_REG_OFFSET);
176 
177  *state = (reg == kMultiBitBool4True) ? kDifToggleEnabled : kDifToggleDisabled;
178 
179  return kDifOk;
180 }
181 
183  dif_toggle_t state) {
184  if (sram_ctrl == NULL) {
185  return kDifBadArg;
186  }
187 
188  if (sram_ctrl_exec_locked(sram_ctrl)) {
189  return kDifLocked;
190  }
191 
192  uint32_t value =
193  (state == kDifToggleEnabled) ? kMultiBitBool4True : kMultiBitBool4False;
194  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_EXEC_REG_OFFSET, value);
195 
196  return kDifOk;
197 }
198 
200  dif_toggle_t state) {
201  if (sram_ctrl == NULL) {
202  return kDifBadArg;
203  }
204 
205  if (sram_ctrl_readback_locked(sram_ctrl)) {
206  return kDifLocked;
207  }
208 
209  uint32_t value =
210  (state == kDifToggleEnabled) ? kMultiBitBool4True : kMultiBitBool4False;
211  mmio_region_write32(sram_ctrl->base_addr, SRAM_CTRL_READBACK_REG_OFFSET,
212  value);
213 
214  return kDifOk;
215 }
216 
218  dif_sram_ctrl_lock_t lock) {
219  if (sram_ctrl == NULL) {
220  return kDifBadArg;
221  }
222 
223  switch (lock) {
225  sram_ctrl_lock_ctrl(sram_ctrl);
226  break;
228  sram_ctrl_lock_exec(sram_ctrl);
229  break;
231  sram_ctrl_lock_readback(sram_ctrl);
232  break;
233  default:
234  return kDifError;
235  }
236 
237  return kDifOk;
238 }
239 
242  bool *is_locked) {
243  if (sram_ctrl == NULL || is_locked == NULL) {
244  return kDifBadArg;
245  }
246 
247  switch (lock) {
249  *is_locked = sram_ctrl_locked_ctrl(sram_ctrl);
250  break;
252  *is_locked = sram_ctrl_exec_locked(sram_ctrl);
253  break;
255  *is_locked = sram_ctrl_readback_locked(sram_ctrl);
256  break;
257  default:
258  return kDifError;
259  }
260 
261  return kDifOk;
262 }
263 
265  multi_bit_bool_t *success,
266  multi_bit_bool_t clear) {
267  if (sram_ctrl == NULL || success == NULL) {
268  return kDifBadArg;
269  }
270 
271  // We do not use any control flow statements to determine whether to clear
272  // the CSR or not. Rather, the register is always written and we let the
273  // MuBi logic determine what needs to be done. I.e., the register is
274  // specified as W1C in which case a clear operation only takes place if
275  // clear is set to kMultiBitBool4True. If it is set to kMultiBitBool4False,
276  // the current state will persist.
277  *success = mmio_region_read32(sram_ctrl->base_addr,
278  SRAM_CTRL_SCR_KEY_ROTATED_REG_OFFSET);
279  mmio_region_write32(sram_ctrl->base_addr,
280  SRAM_CTRL_SCR_KEY_ROTATED_REG_OFFSET, clear);
281 
282  return kDifOk;
283 }