Software APIs
dif_rram_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
9#include "sw/device/lib/base/multibits.h"
10
11// Generated.
13
14/**
15 * Helper function to get the offset of a data region's configuration register.
16 * Does not check that the region actually exists, which is deferred to callers.
17 * Since data region registers are split into two (one containing properties the
18 * other containing address info), there are two helper functions below.
19 *
20 * @param region The data region's index.
21 * @return The offset from the RRAM controller's base address where the region
22 * configuration register is located.
23 */
24static ptrdiff_t get_data_region_mp_reg_offset(uint32_t region) {
25 return RRAM_CTRL_MP_REGION_CFG_0_REG_OFFSET +
26 (ptrdiff_t)region * (ptrdiff_t)sizeof(uint32_t);
27}
28
29static ptrdiff_t get_data_region_reg_offset(uint32_t region) {
30 return RRAM_CTRL_MP_REGION_0_REG_OFFSET +
31 (ptrdiff_t)region * (ptrdiff_t)sizeof(uint32_t);
32}
33
34static ptrdiff_t get_data_region_lock_reg_offset(uint32_t region) {
35 return RRAM_CTRL_REGION_CFG_REGWEN_0_REG_OFFSET +
36 (ptrdiff_t)region * (ptrdiff_t)sizeof(uint32_t);
37}
38
39// generated parameters from hjson
40enum {
41 kNumInfoPages = RRAM_CTRL_PARAM_NUM_INFO_PAGES,
42 kNumDataPages = RRAM_CTRL_PARAM_NUM_DATA_PAGES,
43 kBytesPerWord = RRAM_CTRL_PARAM_BYTES_PER_WORD,
44 kBytesPerPage = RRAM_CTRL_PARAM_BYTES_PER_PAGE,
45 kExecEn = RRAM_CTRL_PARAM_EXEC_EN,
46 kNumRegions = RRAM_CTRL_PARAM_NUM_REGIONS,
47};
48
49/**
50 * Helper function to get the offset of an info region's configuration register.
51 * Does not check that the region actually exists, which is deferred to callers.
52 *
53 * @param region The info region's description.
54 * @return The offset from the RRAM controller's base address where the region
55 * configuration register is located.
56 */
57static ptrdiff_t get_info_region_mp_reg_offset(
59 return RRAM_CTRL_INFO_PAGE_CFG_0_REG_OFFSET +
60 (ptrdiff_t)region.page * (ptrdiff_t)sizeof(uint32_t);
61}
62
63static ptrdiff_t get_info_region_lock_reg_offset(
65 return RRAM_CTRL_INFO_REGWEN_0_REG_OFFSET +
66 (ptrdiff_t)region.page * (ptrdiff_t)sizeof(uint32_t);
67}
68
69dif_result_t dif_rram_ctrl_init_state(dif_rram_ctrl_state_t *handle,
70 mmio_region_t base_addr) {
71 if (handle == NULL) {
72 return kDifBadArg;
73 }
74 DIF_RETURN_IF_ERROR(dif_rram_ctrl_init(base_addr, &handle->dev));
75 handle->words_remaining = 0;
76 handle->transaction_pending = false;
77 return kDifOk;
78}
79
80dif_result_t dif_rram_ctrl_init_state_from_dt(dif_rram_ctrl_state_t *handle,
81 dt_rram_ctrl_t dt) {
82 return dif_rram_ctrl_init_state(
83 handle, mmio_region_from_addr(dt_rram_ctrl_primary_reg_block(dt)));
84}
85
86dif_rram_ctrl_device_info_t dif_rram_ctrl_get_device_info(void) {
87 const dif_rram_ctrl_device_info_t info = {
88 .bytes_per_word = kBytesPerWord,
89 .bytes_per_page = kBytesPerPage,
90 .data_pages = kNumDataPages,
91 .info_pages = kNumInfoPages,
92 };
93 return info;
94}
95
96dif_result_t dif_rram_ctrl_set_rram_enablement(dif_rram_ctrl_state_t *handle,
97 dif_toggle_t enable) {
98 multi_bit_bool_t disable_rram;
99 if (handle == NULL) {
100 return kDifBadArg;
101 }
102 switch (enable) {
104 disable_rram = kMultiBitBool4False;
105 break;
107 disable_rram = kMultiBitBool4True;
108 break;
109 default:
110 return kDifBadArg;
111 }
112 uint32_t reg;
113 reg = mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_DIS_REG_OFFSET);
114 reg = bitfield_field32_write(reg, RRAM_CTRL_DIS_SW_DIS_FIELD, disable_rram);
115 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_DIS_REG_OFFSET, reg);
116 return kDifOk;
117}
118
119dif_result_t dif_rram_ctrl_get_rram_enablement(
120 const dif_rram_ctrl_state_t *handle, dif_toggle_t *enabled_out) {
121 if (handle == NULL || enabled_out == NULL) {
122 return kDifBadArg;
123 }
124 uint32_t reg =
125 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_DIS_REG_OFFSET);
126 multi_bit_bool_t rram_disabled =
127 bitfield_field32_read(reg, RRAM_CTRL_DIS_SW_DIS_FIELD);
128 if (rram_disabled == kMultiBitBool4False) {
129 *enabled_out = kDifToggleEnabled;
130 } else {
131 *enabled_out = kDifToggleDisabled;
132 }
133 return kDifOk;
134}
135
136dif_result_t dif_rram_ctrl_set_exec_enablement(dif_rram_ctrl_state_t *handle,
137 dif_toggle_t enable) {
138 uint32_t value;
139 if (handle == NULL) {
140 return kDifBadArg;
141 }
142 switch (enable) {
144 value = kExecEn;
145 break;
147 value = 0;
148 break;
149 default:
150 return kDifBadArg;
151 }
152 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_EXEC_REG_OFFSET, value);
153 return kDifOk;
154}
155
156dif_result_t dif_rram_ctrl_get_exec_enablement(
157 const dif_rram_ctrl_state_t *handle, dif_toggle_t *enabled_out) {
158 if (handle == NULL || enabled_out == NULL) {
159 return kDifBadArg;
160 }
161 uint32_t reg =
162 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_EXEC_REG_OFFSET);
163 if (reg == kExecEn) {
164 *enabled_out = kDifToggleEnabled;
165 } else {
166 *enabled_out = kDifToggleDisabled;
167 }
168 return kDifOk;
169}
170
171dif_result_t dif_rram_ctrl_start_controller_init(
172 dif_rram_ctrl_state_t *handle) {
173 if (handle == NULL) {
174 return kDifBadArg;
175 }
176 const uint32_t reg =
177 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_INIT_REG_OFFSET);
178 if (bitfield_bit32_read(reg, RRAM_CTRL_INIT_VAL_BIT)) {
179 // Controller initialization may only be requested once.
180 return kDifError;
181 }
182 uint32_t value = bitfield_bit32_write(0, RRAM_CTRL_INIT_VAL_BIT, true);
183 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_INIT_REG_OFFSET, value);
184 return kDifOk;
185}
186
187dif_result_t dif_rram_ctrl_get_status(const dif_rram_ctrl_state_t *handle,
188 dif_rram_ctrl_status_t *status_out) {
189 if (handle == NULL || status_out == NULL) {
190 return kDifBadArg;
191 }
192 uint32_t reg =
193 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_STATUS_REG_OFFSET);
195 .read_fifo_full = bitfield_bit32_read(reg, RRAM_CTRL_STATUS_RD_FULL_BIT),
196 .read_fifo_empty =
197 bitfield_bit32_read(reg, RRAM_CTRL_STATUS_RD_EMPTY_BIT),
198 .write_fifo_full = bitfield_bit32_read(reg, RRAM_CTRL_STATUS_WR_FULL_BIT),
199 .write_fifo_empty =
200 bitfield_bit32_read(reg, RRAM_CTRL_STATUS_WR_EMPTY_BIT),
201 .controller_init_done =
202 bitfield_bit32_read(reg, RRAM_CTRL_STATUS_INIT_DONE_BIT),
203 .controller_keys_valid =
204 bitfield_bit32_read(reg, RRAM_CTRL_STATUS_KEYS_VALID_BIT),
205 };
206 *status_out = status;
207 return kDifOk;
208}
209
210dif_result_t dif_rram_ctrl_start_unsafe(
211 dif_rram_ctrl_state_t *handle, dif_rram_ctrl_transaction_t transaction) {
212 if (handle == NULL) {
213 return kDifBadArg;
214 }
215 uint32_t ctrl_regwen = mmio_region_read32(handle->dev.base_addr,
216 RRAM_CTRL_CTRL_REGWEN_REG_OFFSET);
217 if (!bitfield_bit32_read(ctrl_regwen, RRAM_CTRL_CTRL_REGWEN_EN_BIT)) {
218 return kDifUnavailable;
219 }
220
221 // Hardware ignores the NUM field for kDifRramCtrlOpRewrite (a rewrite always
222 // affects exactly one word), so `transaction.word_count` is not meaningful
223 // for that operation and isn't validated in `dif_rram_ctrl_start()`.
224 uint32_t control_reg = bitfield_field32_write(0, RRAM_CTRL_CONTROL_NUM_FIELD,
225 transaction.word_count - 1);
226 switch (transaction.op) {
228 control_reg =
229 bitfield_field32_write(control_reg, RRAM_CTRL_CONTROL_OP_FIELD,
230 RRAM_CTRL_CONTROL_OP_VALUE_READ);
231 break;
233 control_reg =
234 bitfield_field32_write(control_reg, RRAM_CTRL_CONTROL_OP_FIELD,
235 RRAM_CTRL_CONTROL_OP_VALUE_WRITE);
236 break;
238 control_reg =
239 bitfield_field32_write(control_reg, RRAM_CTRL_CONTROL_OP_FIELD,
240 RRAM_CTRL_CONTROL_OP_VALUE_REWRITE);
241 break;
242 default:
243 return kDifBadArg;
244 }
245
246 switch (transaction.partition_type) {
247 case kDifRramCtrlPartitionTypeData:
248 control_reg = bitfield_bit32_write(
249 control_reg, RRAM_CTRL_CONTROL_PARTITION_BIT, false);
250 break;
251 case kDifRramCtrlPartitionTypeInfo:
252 control_reg = bitfield_bit32_write(control_reg,
253 RRAM_CTRL_CONTROL_PARTITION_BIT, true);
254 break;
255 default:
256 return kDifBadArg;
257 }
258
259 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_CONTROL_REG_OFFSET,
260 control_reg);
261 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_ADDR_REG_OFFSET,
262 transaction.byte_address);
263 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_CONTROL_REG_OFFSET,
264 control_reg | (1u << RRAM_CTRL_CONTROL_START_BIT));
265 if (transaction.op == kDifRramCtrlOpRewrite) {
266 // Rewrite operations don't use the FIFO
267 handle->words_remaining = 0;
268 } else {
269 handle->words_remaining = transaction.word_count;
270 }
271 handle->transaction_pending = true;
272 return kDifOk;
273}
274
275dif_result_t dif_rram_ctrl_start(dif_rram_ctrl_state_t *handle,
276 dif_rram_ctrl_transaction_t transaction) {
277 if (handle == NULL) {
278 return kDifBadArg;
279 }
280
281 const uint32_t max_word_count = RRAM_CTRL_CONTROL_NUM_MASK;
282 if (transaction.op != kDifRramCtrlOpRewrite) {
283 if (transaction.word_count - 1 > max_word_count ||
284 transaction.word_count == 0) {
285 return kDifBadArg;
286 }
287 }
288 // We can only write a multiple of `kBytesPerWord` worth of 32b words.
289 if (transaction.op == kDifRramCtrlOpWrite) {
290 if (transaction.word_count % (kBytesPerWord / sizeof(uint32_t)) != 0) {
291 return kDifBadArg;
292 }
293 }
294
295 // start address must be aligned to `kBytesPerWord` for write operations
296 if (transaction.op == kDifRramCtrlOpWrite) {
297 if (transaction.byte_address % kBytesPerWord != 0) {
298 return kDifBadArg;
299 }
300 }
301
302 if (handle->transaction_pending) {
303 return kDifUnavailable;
304 }
305
306 // Disallow starting a new transaction if the FIFOs haven't been emptied yet.
308 DIF_RETURN_IF_ERROR(dif_rram_ctrl_get_status(handle, &status));
309 if (!status.read_fifo_empty || !status.write_fifo_empty) {
310 return kDifIpFifoFull;
311 }
312
313 return dif_rram_ctrl_start_unsafe(handle, transaction);
314}
315
316dif_result_t dif_rram_ctrl_wr_fifo_push_unsafe(dif_rram_ctrl_state_t *handle,
317 uint32_t word_count,
318 const uint32_t *data) {
319 if (handle == NULL || data == NULL) {
320 return kDifBadArg;
321 }
322 uint32_t written;
323 for (written = 0; written < word_count; ++written) {
324 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_WR_FIFO_REG_OFFSET,
325 data[written]);
326 }
327 handle->words_remaining -= written;
328 return kDifOk;
329}
330
331dif_result_t dif_rram_ctrl_wr_fifo_push(dif_rram_ctrl_state_t *handle,
332 uint32_t word_count,
333 const uint32_t *data) {
334 if (handle == NULL || data == NULL) {
335 return kDifBadArg;
336 }
337 if (!handle->transaction_pending) {
338 return kDifError;
339 }
340 if (handle->words_remaining < word_count) {
341 return kDifBadArg;
342 }
343 const uint32_t control_reg =
344 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_CONTROL_REG_OFFSET);
345 const uint32_t op =
346 bitfield_field32_read(control_reg, RRAM_CTRL_CONTROL_OP_FIELD);
347 if (op != RRAM_CTRL_CONTROL_OP_VALUE_WRITE) {
348 return kDifError;
349 }
350 return dif_rram_ctrl_wr_fifo_push_unsafe(handle, word_count, data);
351}
352
353dif_result_t dif_rram_ctrl_read_fifo_pop_unsafe(dif_rram_ctrl_state_t *handle,
354 uint32_t word_count,
355 uint32_t *data) {
356 if (handle == NULL || data == NULL) {
357 return kDifBadArg;
358 }
359 uint32_t read;
360 for (read = 0; read < word_count; ++read) {
361 data[read] =
362 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_RD_FIFO_REG_OFFSET);
363 }
364 handle->words_remaining -= read;
365 return kDifOk;
366}
367
368dif_result_t dif_rram_ctrl_read_fifo_pop(dif_rram_ctrl_state_t *handle,
369 uint32_t word_count, uint32_t *data) {
370 if (handle == NULL || data == NULL) {
371 return kDifBadArg;
372 }
373 if (!handle->transaction_pending) {
374 return kDifError;
375 }
376 if (handle->words_remaining < word_count) {
377 return kDifBadArg;
378 }
379 const uint32_t control_reg =
380 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_CONTROL_REG_OFFSET);
381 const uint32_t op =
382 bitfield_field32_read(control_reg, RRAM_CTRL_CONTROL_OP_FIELD);
383 if (op != RRAM_CTRL_CONTROL_OP_VALUE_READ) {
384 return kDifError;
385 }
386 return dif_rram_ctrl_read_fifo_pop_unsafe(handle, word_count, data);
387}
388
389dif_result_t dif_rram_ctrl_get_error_codes(
390 const dif_rram_ctrl_state_t *handle,
391 dif_rram_ctrl_error_t *error_code_out) {
392 if (handle == NULL || error_code_out == NULL) {
393 return kDifBadArg;
394 }
395 const uint32_t code_reg =
396 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_ERR_CODE_REG_OFFSET);
397 dif_rram_ctrl_error_codes_t codes = {
398 .operation_error =
399 bitfield_bit32_read(code_reg, RRAM_CTRL_ERR_CODE_OP_ERR_BIT),
400 .memory_protection_error =
401 bitfield_bit32_read(code_reg, RRAM_CTRL_ERR_CODE_MP_ERR_BIT),
402 .read_error =
403 bitfield_bit32_read(code_reg, RRAM_CTRL_ERR_CODE_RD_ERR_BIT),
404 .write_error =
405 bitfield_bit32_read(code_reg, RRAM_CTRL_ERR_CODE_WR_ERR_BIT),
406 };
407
408 const uint32_t address_reg =
409 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_ERR_ADDR_REG_OFFSET);
410 dif_rram_ctrl_error_t error_code = {
411 .address = address_reg,
412 .codes = codes,
413 };
414 *error_code_out = error_code;
415 return kDifOk;
416}
417
418dif_result_t dif_rram_ctrl_clear_error_codes(
419 dif_rram_ctrl_state_t *handle, dif_rram_ctrl_error_codes_t codes) {
420 if (handle == NULL) {
421 return kDifBadArg;
422 }
423 uint32_t code_reg = 0;
424 code_reg = bitfield_bit32_write(code_reg, RRAM_CTRL_ERR_CODE_OP_ERR_BIT,
425 codes.operation_error);
426 code_reg = bitfield_bit32_write(code_reg, RRAM_CTRL_ERR_CODE_MP_ERR_BIT,
428 code_reg = bitfield_bit32_write(code_reg, RRAM_CTRL_ERR_CODE_RD_ERR_BIT,
429 codes.read_error);
430 code_reg = bitfield_bit32_write(code_reg, RRAM_CTRL_ERR_CODE_WR_ERR_BIT,
431 codes.write_error);
432 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_ERR_CODE_REG_OFFSET,
433 code_reg);
434 return kDifOk;
435}
436
437dif_result_t dif_rram_ctrl_end(dif_rram_ctrl_state_t *handle,
438 dif_rram_ctrl_output_t *out) {
439 if (handle == NULL || out == NULL) {
440 return kDifBadArg;
441 }
442 if (!handle->transaction_pending) {
443 return kDifError;
444 }
445 uint32_t status_reg =
446 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_OP_STATUS_REG_OFFSET);
447 if (!bitfield_bit32_read(status_reg, RRAM_CTRL_OP_STATUS_DONE_BIT)) {
448 return kDifUnavailable;
449 }
450 if (handle->words_remaining != 0) {
451 return kDifIpFifoFull;
452 }
453 dif_rram_ctrl_error_t error_code_tmp;
454 DIF_RETURN_IF_ERROR(dif_rram_ctrl_get_error_codes(handle, &error_code_tmp));
455 dif_rram_ctrl_output_t output = {
456 .operation_done =
457 bitfield_bit32_read(status_reg, RRAM_CTRL_OP_STATUS_DONE_BIT),
458 .operation_error =
459 bitfield_bit32_read(status_reg, RRAM_CTRL_OP_STATUS_ERR_BIT),
460 .error_code = error_code_tmp};
461 // Clear the operation status
462 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_OP_STATUS_REG_OFFSET, 0);
463 handle->transaction_pending = false;
464 *out = output;
465 return kDifOk;
466}
467
468dif_result_t dif_rram_ctrl_set_data_region_enablement(
469 dif_rram_ctrl_state_t *handle, uint32_t region, dif_toggle_t enable) {
470 if (handle == NULL || region >= kNumRegions) {
471 return kDifBadArg;
472 }
473
474 bool locked;
476 dif_rram_ctrl_data_region_is_locked(handle, region, &locked));
477 if (locked) {
478 return kDifLocked;
479 }
480
481 ptrdiff_t mp_reg_offset = get_data_region_mp_reg_offset(region);
482 uint32_t mp_reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
483 switch (enable) {
485 mp_reg = bitfield_field32_write(
486 mp_reg, RRAM_CTRL_MP_REGION_CFG_0_EN_0_FIELD, kMultiBitBool4True);
487 break;
489 mp_reg = bitfield_field32_write(
490 mp_reg, RRAM_CTRL_MP_REGION_CFG_0_EN_0_FIELD, kMultiBitBool4False);
491 break;
492 default:
493 return kDifBadArg;
494 }
495 mmio_region_write32(handle->dev.base_addr, mp_reg_offset, mp_reg);
496 return kDifOk;
497}
498
499dif_result_t dif_rram_ctrl_get_data_region_enablement(
500 const dif_rram_ctrl_state_t *handle, uint32_t region,
501 dif_toggle_t *enabled_out) {
502 if (handle == NULL || enabled_out == NULL || region >= kNumRegions) {
503 return kDifBadArg;
504 }
505 ptrdiff_t mp_reg_offset = get_data_region_mp_reg_offset(region);
506 uint32_t mp_reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
507 if (bitfield_field32_read(mp_reg, RRAM_CTRL_MP_REGION_CFG_0_EN_0_FIELD) ==
508 kMultiBitBool4True) {
509 *enabled_out = kDifToggleEnabled;
510 } else {
511 *enabled_out = kDifToggleDisabled;
512 }
513 return kDifOk;
514}
515
516dif_result_t dif_rram_ctrl_set_info_region_enablement(
518 dif_toggle_t enable) {
519 if (handle == NULL || region.page >= kNumInfoPages) {
520 return kDifBadArg;
521 }
522 bool locked;
524 dif_rram_ctrl_info_region_is_locked(handle, region, &locked));
525 if (locked) {
526 return kDifLocked;
527 }
528
529 ptrdiff_t mp_reg_offset = get_info_region_mp_reg_offset(region);
530 uint32_t mp_reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
531 switch (enable) {
533 mp_reg = bitfield_field32_write(
534 mp_reg, RRAM_CTRL_INFO_PAGE_CFG_0_EN_0_FIELD, kMultiBitBool4True);
535 break;
537 mp_reg = bitfield_field32_write(
538 mp_reg, RRAM_CTRL_INFO_PAGE_CFG_0_EN_0_FIELD, kMultiBitBool4False);
539 break;
540 default:
541 return kDifBadArg;
542 }
543 mmio_region_write32(handle->dev.base_addr, mp_reg_offset, mp_reg);
544 return kDifOk;
545}
546
547dif_result_t dif_rram_ctrl_get_info_region_enablement(
549 dif_toggle_t *enabled_out) {
550 if (handle == NULL || enabled_out == NULL || region.page >= kNumInfoPages) {
551 return kDifBadArg;
552 }
553 ptrdiff_t mp_reg_offset = get_info_region_mp_reg_offset(region);
554 uint32_t mp_reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
555 if (bitfield_field32_read(mp_reg, RRAM_CTRL_INFO_PAGE_CFG_0_EN_0_FIELD) ==
556 kMultiBitBool4True) {
557 *enabled_out = kDifToggleEnabled;
558 } else {
559 *enabled_out = kDifToggleDisabled;
560 }
561 return kDifOk;
562}
563
564dif_result_t dif_rram_ctrl_set_default_region_properties(
565 dif_rram_ctrl_state_t *handle,
567 if (handle == NULL) {
568 return kDifBadArg;
569 }
570 uint32_t reg = 0;
571 reg = bitfield_field32_write(reg, RRAM_CTRL_DEFAULT_REGION_RD_EN_FIELD,
572 properties.rd_en);
573 reg = bitfield_field32_write(reg, RRAM_CTRL_DEFAULT_REGION_WR_EN_FIELD,
574 properties.wr_en);
575 reg = bitfield_field32_write(reg, RRAM_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD,
576 properties.scramble_en);
577 reg = bitfield_field32_write(reg, RRAM_CTRL_DEFAULT_REGION_ECC_EN_FIELD,
578 properties.ecc_en);
579 mmio_region_write32(handle->dev.base_addr,
580 RRAM_CTRL_DEFAULT_REGION_REG_OFFSET, reg);
581 return kDifOk;
582}
583
584dif_result_t dif_rram_ctrl_get_default_region_properties(
585 const dif_rram_ctrl_state_t *handle,
586 dif_rram_ctrl_region_properties_t *properties_out) {
587 if (handle == NULL || properties_out == NULL) {
588 return kDifBadArg;
589 }
590 const uint32_t reg = mmio_region_read32(handle->dev.base_addr,
591 RRAM_CTRL_DEFAULT_REGION_REG_OFFSET);
593 .rd_en = bitfield_field32_read(reg, RRAM_CTRL_DEFAULT_REGION_RD_EN_FIELD),
594 .wr_en = bitfield_field32_read(reg, RRAM_CTRL_DEFAULT_REGION_WR_EN_FIELD),
595 .scramble_en = bitfield_field32_read(
596 reg, RRAM_CTRL_DEFAULT_REGION_SCRAMBLE_EN_FIELD),
597 .ecc_en =
598 bitfield_field32_read(reg, RRAM_CTRL_DEFAULT_REGION_ECC_EN_FIELD),
599 };
600 *properties_out = properties;
601 return kDifOk;
602}
603
604dif_result_t dif_rram_ctrl_set_data_region_properties(
605 dif_rram_ctrl_state_t *handle, uint32_t region,
607 const uint32_t page_limit = kNumDataPages;
608 if (handle == NULL || region >= kNumRegions ||
609 config.base + config.size > page_limit) {
610 return kDifBadArg;
611 }
612
613 bool locked;
615 dif_rram_ctrl_data_region_is_locked(handle, region, &locked));
616 if (locked) {
617 return kDifLocked;
618 }
619
620 ptrdiff_t mp_reg_offset = get_data_region_mp_reg_offset(region);
621 uint32_t reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
622 reg = bitfield_field32_write(reg, RRAM_CTRL_MP_REGION_CFG_0_RD_EN_0_FIELD,
623 config.properties.rd_en);
624 reg = bitfield_field32_write(reg, RRAM_CTRL_MP_REGION_CFG_0_WR_EN_0_FIELD,
625 config.properties.wr_en);
626 reg =
627 bitfield_field32_write(reg, RRAM_CTRL_MP_REGION_CFG_0_SCRAMBLE_EN_0_FIELD,
628 config.properties.scramble_en);
629 reg = bitfield_field32_write(reg, RRAM_CTRL_MP_REGION_CFG_0_ECC_EN_0_FIELD,
630 config.properties.ecc_en);
631
632 mmio_region_write32(handle->dev.base_addr, mp_reg_offset, reg);
633
634 // size and base are stored in different registers
635 mp_reg_offset = get_data_region_reg_offset(region);
636
637 reg = bitfield_field32_write(0, RRAM_CTRL_MP_REGION_0_BASE_0_FIELD,
638 config.base);
639 reg = bitfield_field32_write(reg, RRAM_CTRL_MP_REGION_0_SIZE_0_FIELD,
640 config.size);
641 mmio_region_write32(handle->dev.base_addr, mp_reg_offset, reg);
642 return kDifOk;
643}
644
645dif_result_t dif_rram_ctrl_get_data_region_properties(
646 const dif_rram_ctrl_state_t *handle, uint32_t region,
648 if (handle == NULL || config_out == NULL || region >= kNumRegions) {
649 return kDifBadArg;
650 }
651
652 ptrdiff_t mp_reg_offset = get_data_region_mp_reg_offset(region);
653 uint32_t reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
655 config.properties.rd_en =
656 bitfield_field32_read(reg, RRAM_CTRL_MP_REGION_CFG_0_RD_EN_0_FIELD);
657 config.properties.wr_en =
658 bitfield_field32_read(reg, RRAM_CTRL_MP_REGION_CFG_0_WR_EN_0_FIELD);
659 config.properties.scramble_en =
660 bitfield_field32_read(reg, RRAM_CTRL_MP_REGION_CFG_0_SCRAMBLE_EN_0_FIELD);
661 config.properties.ecc_en =
662 bitfield_field32_read(reg, RRAM_CTRL_MP_REGION_CFG_0_ECC_EN_0_FIELD);
663
664 mp_reg_offset = get_data_region_reg_offset(region);
665 reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
666 config.base = bitfield_field32_read(reg, RRAM_CTRL_MP_REGION_0_BASE_0_FIELD);
667 config.size = bitfield_field32_read(reg, RRAM_CTRL_MP_REGION_0_SIZE_0_FIELD);
668 *config_out = config;
669 return kDifOk;
670}
671
672dif_result_t dif_rram_ctrl_set_info_region_properties(
675 if (handle == NULL || region.page >= kNumInfoPages) {
676 return kDifBadArg;
677 }
678
679 bool locked;
681 dif_rram_ctrl_info_region_is_locked(handle, region, &locked));
682 if (locked) {
683 return kDifLocked;
684 }
685
686 ptrdiff_t mp_reg_offset = get_info_region_mp_reg_offset(region);
687 uint32_t reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
688 reg = bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_RD_EN_0_FIELD,
689 properties.rd_en);
690 reg = bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_WR_EN_0_FIELD,
691 properties.wr_en);
692 reg =
693 bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_SCRAMBLE_EN_0_FIELD,
694 properties.scramble_en);
695 reg = bitfield_field32_write(reg, RRAM_CTRL_INFO_PAGE_CFG_0_ECC_EN_0_FIELD,
696 properties.ecc_en);
697 mmio_region_write32(handle->dev.base_addr, mp_reg_offset, reg);
698 return kDifOk;
699}
700
701dif_result_t dif_rram_ctrl_get_info_region_properties(
703 dif_rram_ctrl_region_properties_t *properties_out) {
704 if (handle == NULL || properties_out == NULL ||
705 region.page >= kNumInfoPages) {
706 return kDifBadArg;
707 }
708
709 ptrdiff_t mp_reg_offset = get_info_region_mp_reg_offset(region);
710 const uint32_t reg = mmio_region_read32(handle->dev.base_addr, mp_reg_offset);
712 properties.rd_en =
713 bitfield_field32_read(reg, RRAM_CTRL_INFO_PAGE_CFG_0_RD_EN_0_FIELD);
714 properties.wr_en =
715 bitfield_field32_read(reg, RRAM_CTRL_INFO_PAGE_CFG_0_WR_EN_0_FIELD);
716 properties.scramble_en =
717 bitfield_field32_read(reg, RRAM_CTRL_INFO_PAGE_CFG_0_SCRAMBLE_EN_0_FIELD);
718 properties.ecc_en =
719 bitfield_field32_read(reg, RRAM_CTRL_INFO_PAGE_CFG_0_ECC_EN_0_FIELD);
720 *properties_out = properties;
721 return kDifOk;
722}
723
724dif_result_t dif_rram_ctrl_lock_data_region_properties(
725 dif_rram_ctrl_state_t *handle, uint32_t region) {
726 if (handle == NULL || region >= kNumRegions) {
727 return kDifBadArg;
728 }
729
730 bool locked;
732 dif_rram_ctrl_data_region_is_locked(handle, region, &locked));
733 if (locked) {
734 return kDifLocked;
735 }
736
737 ptrdiff_t lock_reg_offset = get_data_region_lock_reg_offset(region);
738 // rw0c: write 0 to lock.
739 mmio_region_write32(handle->dev.base_addr, lock_reg_offset, 0);
740 return kDifOk;
741}
742
743dif_result_t dif_rram_ctrl_lock_info_region_properties(
745 if (handle == NULL || region.page >= kNumInfoPages) {
746 return kDifBadArg;
747 }
748
749 bool locked;
751 dif_rram_ctrl_info_region_is_locked(handle, region, &locked));
752 if (locked) {
753 return kDifLocked;
754 }
755
756 ptrdiff_t lock_reg_offset = get_info_region_lock_reg_offset(region);
757 // rw0c: write 0 to lock.
758 mmio_region_write32(handle->dev.base_addr, lock_reg_offset, 0);
759 return kDifOk;
760}
761
762dif_result_t dif_rram_ctrl_data_region_is_locked(
763 const dif_rram_ctrl_state_t *handle, uint32_t region, bool *locked_out) {
764 if (handle == NULL || locked_out == NULL || region >= kNumRegions) {
765 return kDifBadArg;
766 }
767 ptrdiff_t lock_reg_offset = get_data_region_lock_reg_offset(region);
768 uint32_t reg = mmio_region_read32(handle->dev.base_addr, lock_reg_offset);
769 *locked_out =
770 !bitfield_bit32_read(reg, RRAM_CTRL_REGION_CFG_REGWEN_0_REGION_0_BIT);
771 return kDifOk;
772}
773
774dif_result_t dif_rram_ctrl_info_region_is_locked(
776 bool *locked_out) {
777 if (handle == NULL || locked_out == NULL || region.page >= kNumInfoPages) {
778 return kDifBadArg;
779 }
780
781 ptrdiff_t lock_reg_offset = get_info_region_lock_reg_offset(region);
782 uint32_t reg = mmio_region_read32(handle->dev.base_addr, lock_reg_offset);
783 *locked_out = !bitfield_bit32_read(reg, RRAM_CTRL_INFO_REGWEN_0_REGION_0_BIT);
784 return kDifOk;
785}
786
787dif_result_t dif_rram_ctrl_set_wr_fifo_watermark(dif_rram_ctrl_state_t *handle,
788 uint32_t level) {
789 if (handle == NULL || level > RRAM_CTRL_FIFO_LVL_WR_MASK) {
790 return kDifBadArg;
791 }
792 uint32_t reg =
793 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_FIFO_LVL_REG_OFFSET);
794 reg = bitfield_field32_write(reg, RRAM_CTRL_FIFO_LVL_WR_FIELD, level);
795 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_FIFO_LVL_REG_OFFSET,
796 reg);
797 return kDifOk;
798}
799
800dif_result_t dif_rram_ctrl_set_read_fifo_watermark(
801 dif_rram_ctrl_state_t *handle, uint32_t level) {
802 if (handle == NULL || level > RRAM_CTRL_FIFO_LVL_RD_MASK) {
803 return kDifBadArg;
804 }
805 uint32_t reg =
806 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_FIFO_LVL_REG_OFFSET);
807 reg = bitfield_field32_write(reg, RRAM_CTRL_FIFO_LVL_RD_FIELD, level);
808 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_FIFO_LVL_REG_OFFSET,
809 reg);
810 return kDifOk;
811}
812
813dif_result_t dif_rram_ctrl_get_fifo_watermarks(
814 const dif_rram_ctrl_state_t *handle, uint32_t *write_out,
815 uint32_t *read_out) {
816 if (handle == NULL) {
817 return kDifBadArg;
818 }
819 const uint32_t reg =
820 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_FIFO_LVL_REG_OFFSET);
821 if (write_out != NULL) {
822 *write_out = bitfield_field32_read(reg, RRAM_CTRL_FIFO_LVL_WR_FIELD);
823 }
824 if (read_out != NULL) {
825 *read_out = bitfield_field32_read(reg, RRAM_CTRL_FIFO_LVL_RD_FIELD);
826 }
827 return kDifOk;
828}
829
830dif_result_t dif_rram_ctrl_clear_wr_fifo(dif_rram_ctrl_state_t *handle) {
831 if (handle == NULL) {
832 return kDifBadArg;
833 }
834 uint32_t reg = bitfield_bit32_write(0, RRAM_CTRL_FIFO_CLR_WR_BIT, true);
835 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_FIFO_CLR_REG_OFFSET,
836 reg);
837 return kDifOk;
838}
839
840dif_result_t dif_rram_ctrl_clear_rd_fifo(dif_rram_ctrl_state_t *handle) {
841 if (handle == NULL) {
842 return kDifBadArg;
843 }
844 uint32_t reg = bitfield_bit32_write(0, RRAM_CTRL_FIFO_CLR_RD_BIT, true);
845 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_FIFO_CLR_REG_OFFSET,
846 reg);
847 return kDifOk;
848}
849
850dif_result_t dif_rram_ctrl_get_faults(const dif_rram_ctrl_state_t *handle,
851 dif_rram_ctrl_faults_t *faults_out) {
852 if (handle == NULL || faults_out == NULL) {
853 return kDifBadArg;
854 }
855 uint32_t reg = mmio_region_read32(handle->dev.base_addr,
856 RRAM_CTRL_FAULT_STATUS_REG_OFFSET);
857 dif_rram_ctrl_faults_t faults;
858 faults.lcmgr_operation_error =
859 bitfield_bit32_read(reg, RRAM_CTRL_FAULT_STATUS_LCMGR_OP_ERR_BIT);
861 bitfield_bit32_read(reg, RRAM_CTRL_FAULT_STATUS_LCMGR_MP_ERR_BIT);
862 faults.lcmgr_read_error =
863 bitfield_bit32_read(reg, RRAM_CTRL_FAULT_STATUS_LCMGR_RD_ERR_BIT);
864 faults.lcmgr_write_error =
865 bitfield_bit32_read(reg, RRAM_CTRL_FAULT_STATUS_LCMGR_WR_ERR_BIT);
866 faults.otp_operation_error =
867 bitfield_bit32_read(reg, RRAM_CTRL_FAULT_STATUS_OTP_OP_ERR_BIT);
869 bitfield_bit32_read(reg, RRAM_CTRL_FAULT_STATUS_OTP_MP_ERR_BIT);
870 faults.otp_read_error =
871 bitfield_bit32_read(reg, RRAM_CTRL_FAULT_STATUS_OTP_RD_ERR_BIT);
872 faults.otp_write_error =
873 bitfield_bit32_read(reg, RRAM_CTRL_FAULT_STATUS_OTP_WR_ERR_BIT);
874 // TODO: Add more faults?
875 *faults_out = faults;
876 return kDifOk;
877}
878
879dif_result_t dif_rram_ctrl_get_ecc_errors(
880 const dif_rram_ctrl_state_t *handle,
881 dif_rram_ctrl_ecc_errors_t *errors_out) {
882 if (handle == NULL || errors_out == NULL) {
883 return kDifBadArg;
884 }
885
886 uint32_t reg = mmio_region_read32(handle->dev.base_addr,
887 RRAM_CTRL_CORR_ERR_CNT_REG_OFFSET);
888 errors_out->corr_error_count =
889 bitfield_field32_read(reg, RRAM_CTRL_CORR_ERR_CNT_VAL_FIELD);
890
891 reg = mmio_region_read32(handle->dev.base_addr,
892 RRAM_CTRL_CORR_ERR_LOC_REG_OFFSET);
893
894 errors_out->last_error_address =
895 bitfield_field32_read(reg, RRAM_CTRL_CORR_ERR_LOC_ADDR_FIELD);
896 errors_out->last_error_partition =
897 bitfield_bit32_read(reg, RRAM_CTRL_CORR_ERR_LOC_PART_BIT);
898 return kDifOk;
899}
900
901dif_result_t dif_rram_ctrl_get_phy_status(
902 const dif_rram_ctrl_state_t *handle,
903 dif_rram_ctrl_phy_status_t *status_out) {
904 if (handle == NULL || status_out == NULL) {
905 return kDifBadArg;
906 }
907 const uint32_t reg = mmio_region_read32(handle->dev.base_addr,
908 RRAM_CTRL_PHY_STATUS_REG_OFFSET);
909 dif_rram_ctrl_phy_status_t status = {
910 .phy_init_done =
911 bitfield_bit32_read(reg, RRAM_CTRL_PHY_STATUS_INIT_DONE_BIT),
912 .phy_wr_busy = bitfield_bit32_read(reg, RRAM_CTRL_PHY_STATUS_WR_BUSY_BIT),
913 };
914 *status_out = status;
915 return kDifOk;
916}
917
918dif_result_t dif_rram_ctrl_set_scratch(dif_rram_ctrl_state_t *handle,
919 uint32_t value) {
920 if (handle == NULL) {
921 return kDifBadArg;
922 }
923 mmio_region_write32(handle->dev.base_addr, RRAM_CTRL_SCRATCH_REG_OFFSET,
924 value);
925 return kDifOk;
926}
927
928dif_result_t dif_rram_ctrl_get_scratch(const dif_rram_ctrl_state_t *handle,
929 uint32_t *value_out) {
930 if (handle == NULL || value_out == NULL) {
931 return kDifBadArg;
932 }
933 *value_out =
934 mmio_region_read32(handle->dev.base_addr, RRAM_CTRL_SCRATCH_REG_OFFSET);
935 return kDifOk;
936}