Software APIs
dif_entropy_src.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 <stddef.h>
8
12#include "sw/device/lib/base/multibits.h"
14
15#include "hw/top/entropy_src_regs.h" // Generated.
16
17dif_result_t dif_entropy_src_stop(const dif_entropy_src_t *entropy_src) {
18 if (entropy_src == NULL) {
19 return kDifBadArg;
20 }
21
22 mmio_region_write32(entropy_src->base_addr,
23 ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
24 ENTROPY_SRC_MODULE_ENABLE_REG_RESVAL);
25
26 // once disabled, the entropy_src regwen is released
27 if (!mmio_region_read32(entropy_src->base_addr,
28 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
29 return kDifLocked;
30 }
31
32 // set back to default value
33 mmio_region_write32(entropy_src->base_addr,
34 ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET,
35 ENTROPY_SRC_ENTROPY_CONTROL_REG_RESVAL);
36
37 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_CONF_REG_OFFSET,
38 ENTROPY_SRC_CONF_REG_RESVAL);
39
40 mmio_region_write32(entropy_src->base_addr,
41 ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET,
42 ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_RESVAL);
43
44 mmio_region_write32(entropy_src->base_addr,
45 ENTROPY_SRC_ALERT_THRESHOLD_REG_OFFSET,
46 ENTROPY_SRC_ALERT_THRESHOLD_REG_RESVAL);
47
48 return kDifOk;
49}
50
51dif_result_t dif_entropy_src_configure(const dif_entropy_src_t *entropy_src,
53 dif_toggle_t enabled) {
54 if (entropy_src == NULL ||
56 !dif_is_valid_toggle(enabled) || config.health_test_window_size == 0) {
57 return kDifBadArg;
58 }
59
60 if (!mmio_region_read32(entropy_src->base_addr,
61 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
62 return kDifLocked;
63 }
64
65 // ENTROPY_CONTROL register configuration.
66 uint32_t entropy_ctrl_reg = bitfield_field32_write(
67 0, ENTROPY_SRC_ENTROPY_CONTROL_ES_ROUTE_FIELD,
68 config.route_to_firmware ? kMultiBitBool4True : kMultiBitBool4False);
69 entropy_ctrl_reg = bitfield_field32_write(
70 entropy_ctrl_reg, ENTROPY_SRC_ENTROPY_CONTROL_ES_TYPE_FIELD,
71 config.bypass_conditioner ? kMultiBitBool4True : kMultiBitBool4False);
72 mmio_region_write32(entropy_src->base_addr,
73 ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET, entropy_ctrl_reg);
74
75 // CONF register configuration.
76
77 // Configure FIPS enable.
78 // TODO: Add additional DIF to toggle this bit independently.
79 uint32_t entropy_conf_reg = bitfield_field32_write(
80 0, ENTROPY_SRC_CONF_FIPS_ENABLE_FIELD,
81 config.fips_enable ? kMultiBitBool4True : kMultiBitBool4False);
82
83 // Configure FIPS flag.
84 entropy_conf_reg = bitfield_field32_write(
85 entropy_conf_reg, ENTROPY_SRC_CONF_FIPS_FLAG_FIELD,
86 config.fips_flag ? kMultiBitBool4True : kMultiBitBool4False);
87
88 // Configure RNG FIPS.
89 entropy_conf_reg = bitfield_field32_write(
90 entropy_conf_reg, ENTROPY_SRC_CONF_RNG_FIPS_FIELD,
91 config.rng_fips ? kMultiBitBool4True : kMultiBitBool4False);
92
93 // Configure entropy data register enable (enables firmware to read entropy).
94 entropy_conf_reg = bitfield_field32_write(
95 entropy_conf_reg, ENTROPY_SRC_CONF_ENTROPY_DATA_REG_ENABLE_FIELD,
96 config.route_to_firmware ? kMultiBitBool4True : kMultiBitBool4False);
97
98 // Configure the health test threshold scope.
99 entropy_conf_reg = bitfield_field32_write(
100 entropy_conf_reg, ENTROPY_SRC_CONF_THRESHOLD_SCOPE_FIELD,
101 config.health_test_threshold_scope ? kMultiBitBool4True
102 : kMultiBitBool4False);
103
104 // Configure single RNG bit mode.
105 uint32_t rng_bit_en =
107 ? kMultiBitBool4False
108 : kMultiBitBool4True;
109 entropy_conf_reg = bitfield_field32_write(
110 entropy_conf_reg, ENTROPY_SRC_CONF_RNG_BIT_ENABLE_FIELD, rng_bit_en);
111 uint32_t rng_bit_sel =
112 (rng_bit_en == kMultiBitBool4True) ? config.single_bit_mode : 0;
113 entropy_conf_reg = bitfield_field32_write(
114 entropy_conf_reg, ENTROPY_SRC_CONF_RNG_BIT_SEL_FIELD, rng_bit_sel);
115
116 uint32_t sw_rd_en =
117 config.route_to_firmware ? kMultiBitBool4True : kMultiBitBool4False;
118 entropy_conf_reg = bitfield_field32_write(
119 entropy_conf_reg, ENTROPY_SRC_CONF_ENTROPY_DATA_REG_ENABLE_FIELD,
120 sw_rd_en);
121
122 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_CONF_REG_OFFSET,
123 entropy_conf_reg);
124
125 // Configure health test window.
126 // Note: the only supported bypass window size is the default value of 0x60 at
127 // the moment, hence even if `bypass_conditioner` is set, we should not change
128 // the bypass window size.
129 uint32_t health_test_window_sizes =
130 bitfield_field32_write(ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_RESVAL,
131 ENTROPY_SRC_HEALTH_TEST_WINDOWS_FIPS_WINDOW_FIELD,
133 mmio_region_write32(entropy_src->base_addr,
134 ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET,
135 health_test_window_sizes);
136
137 // Alert Threshold register configuration.
138 uint32_t alert_threshold = bitfield_field32_write(
139 0, ENTROPY_SRC_ALERT_THRESHOLD_ALERT_THRESHOLD_FIELD,
140 config.alert_threshold);
141 alert_threshold = bitfield_field32_write(
142 alert_threshold, ENTROPY_SRC_ALERT_THRESHOLD_ALERT_THRESHOLD_INV_FIELD,
143 ~(uint32_t)config.alert_threshold);
144 mmio_region_write32(entropy_src->base_addr,
145 ENTROPY_SRC_ALERT_THRESHOLD_REG_OFFSET, alert_threshold);
146
147 // MODULE_ENABLE register configuration.
148 mmio_region_write32(entropy_src->base_addr,
149 ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
150 dif_toggle_to_multi_bit_bool4(enabled));
151
152 return kDifOk;
153}
154
155dif_result_t dif_entropy_src_fw_override_configure(
156 const dif_entropy_src_t *entropy_src,
158 if (entropy_src == NULL ||
159 config.buffer_threshold >
160 ENTROPY_SRC_OBSERVE_FIFO_THRESH_OBSERVE_FIFO_THRESH_MASK ||
161 config.buffer_threshold == 0 || !dif_is_valid_toggle(enabled)) {
162 return kDifBadArg;
163 }
164
165 if (!mmio_region_read32(entropy_src->base_addr,
166 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
167 return kDifLocked;
168 }
169
170 mmio_region_write32(entropy_src->base_addr,
171 ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET,
172 config.buffer_threshold);
173
174 uint32_t reg =
175 bitfield_field32_write(0, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD,
176 dif_toggle_to_multi_bit_bool4(enabled));
177 reg = bitfield_field32_write(
178 reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_FIELD,
179 config.entropy_insert_enable ? kMultiBitBool4True : kMultiBitBool4False);
180 mmio_region_write32(entropy_src->base_addr,
181 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET, reg);
182
183 return kDifOk;
184}
185
186dif_result_t dif_entropy_src_fw_override_sha3_start_insert(
187 const dif_entropy_src_t *entropy_src, dif_toggle_t enabled) {
188 if (entropy_src == NULL) {
189 return kDifBadArg;
190 }
191
192 uint32_t reg = bitfield_field32_write(
193 0, ENTROPY_SRC_FW_OV_SHA3_START_FW_OV_INSERT_START_FIELD,
194 dif_toggle_to_multi_bit_bool4(enabled));
195 mmio_region_write32(entropy_src->base_addr,
196 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET, reg);
197
198 return kDifOk;
199}
200
201dif_result_t dif_entropy_src_health_test_configure(
202 const dif_entropy_src_t *entropy_src,
204 if (entropy_src == NULL) {
205 return kDifBadArg;
206 }
207
208 if (!mmio_region_read32(entropy_src->base_addr,
209 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
210 return kDifLocked;
211 }
212
213 ptrdiff_t high_threshold_reg_offset = -1;
214 ptrdiff_t low_threshold_reg_offset = -1;
215 switch (config.test_type) {
217 high_threshold_reg_offset = ENTROPY_SRC_REPCNT_THRESHOLD_REG_OFFSET;
218 // Ensure low threshold is zero. There is no low threshold for this test.
219 if (config.low_threshold) {
220 return kDifBadArg;
221 }
222 break;
224 high_threshold_reg_offset = ENTROPY_SRC_REPCNTS_THRESHOLD_REG_OFFSET;
225 // Ensure low threshold is zero. There is no low threshold for this test.
226 if (config.low_threshold) {
227 return kDifBadArg;
228 }
229 break;
231 high_threshold_reg_offset = ENTROPY_SRC_ADAPTP_HI_THRESHOLD_REG_OFFSET;
232 low_threshold_reg_offset = ENTROPY_SRC_ADAPTP_LO_THRESHOLD_REG_OFFSET;
233 break;
235 high_threshold_reg_offset = ENTROPY_SRC_BUCKET_THRESHOLD_REG_OFFSET;
236 // Ensure low threshold is zero. There is no low threshold for this test.
237 if (config.low_threshold) {
238 return kDifBadArg;
239 }
240 break;
242 high_threshold_reg_offset = ENTROPY_SRC_MARKOV_HI_THRESHOLD_REG_OFFSET;
243 low_threshold_reg_offset = ENTROPY_SRC_MARKOV_LO_THRESHOLD_REG_OFFSET;
244 break;
246 high_threshold_reg_offset = ENTROPY_SRC_EXTHT_HI_THRESHOLD_REG_OFFSET;
247 low_threshold_reg_offset = ENTROPY_SRC_EXTHT_LO_THRESHOLD_REG_OFFSET;
248 break;
249 default:
250 return kDifBadArg;
251 }
252
253 mmio_region_write32(entropy_src->base_addr, high_threshold_reg_offset,
254 config.high_threshold);
255 if (low_threshold_reg_offset != -1) {
256 mmio_region_write32(entropy_src->base_addr, low_threshold_reg_offset,
257 config.low_threshold);
258 }
259
260 return kDifOk;
261}
262
263dif_result_t dif_entropy_src_health_test_threshold_oneway_enable(
264 const dif_entropy_src_t *entropy_src) {
265 if (entropy_src == NULL) {
266 return kDifBadArg;
267 }
268
269 mmio_region_write32(entropy_src->base_addr,
270 ENTROPY_SRC_THRESHOLD_ONEWAY_REG_OFFSET,
271 kMultiBitBool4True);
272
273 return kDifOk;
274}
275
276dif_result_t dif_entropy_src_watermark_configure(
277 const dif_entropy_src_t *entropy_src,
279 if (entropy_src == NULL) {
280 return kDifBadArg;
281 }
282
283 if (!mmio_region_read32(entropy_src->base_addr,
284 ENTROPY_SRC_REGWEN_REG_OFFSET)) {
285 return kDifLocked;
286 }
287
288 // Write the specified value.
289 mmio_region_write32(entropy_src->base_addr,
290 ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET, config);
291
292 // Read the value back. In case it doesn't match the previously written
293 // value, the specified value isn't supported.
294 uint32_t ht_watermark_num = mmio_region_read32(
295 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET);
296 if ((uint32_t)config != ht_watermark_num) {
297 return kDifError;
298 }
299
300 return kDifOk;
301}
302
303dif_result_t dif_entropy_src_set_enabled(const dif_entropy_src_t *entropy_src,
304 dif_toggle_t enabled) {
305 if (entropy_src == NULL || !dif_is_valid_toggle(enabled)) {
306 return kDifBadArg;
307 }
308
309 if (!mmio_region_read32(entropy_src->base_addr,
310 ENTROPY_SRC_ME_REGWEN_REG_OFFSET)) {
311 return kDifLocked;
312 }
313
314 mmio_region_write32(entropy_src->base_addr,
315 ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
316 dif_toggle_to_multi_bit_bool4(enabled));
317
318 return kDifOk;
319}
320
321dif_result_t dif_entropy_src_lock(const dif_entropy_src_t *entropy_src) {
322 if (entropy_src == NULL) {
323 return kDifBadArg;
324 }
325
326 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET,
327 0);
328 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_SW_REGUPD_REG_OFFSET,
329 0);
330
331 return kDifOk;
332}
333
334dif_result_t dif_entropy_src_is_locked(const dif_entropy_src_t *entropy_src,
335 bool *is_locked) {
336 if (entropy_src == NULL || is_locked == NULL) {
337 return kDifBadArg;
338 }
339
340 uint32_t module_enable_regwen = mmio_region_read32(
341 entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET);
342 uint32_t sw_regupd = mmio_region_read32(entropy_src->base_addr,
343 ENTROPY_SRC_SW_REGUPD_REG_OFFSET);
344 if (module_enable_regwen == sw_regupd) {
345 *is_locked = sw_regupd == 0;
346 } else {
347 // Since we actuate these together, either both should be 0 (locked), or
348 // both should be 1 (unlocked). If only one is locked, then we have
349 // gotten into a bad state.
350 return kDifError;
351 }
352
353 return kDifOk;
354}
355
356dif_result_t dif_entropy_src_get_health_test_stats(
357 const dif_entropy_src_t *entropy_src,
359 if (entropy_src == NULL || stats == NULL) {
360 return kDifBadArg;
361 }
362
363 stats->watermark_num = (dif_entropy_src_watermark_num_t)mmio_region_read32(
364 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_NUM_REG_OFFSET);
365 stats->watermark = (uint16_t)mmio_region_read32(
366 entropy_src->base_addr, ENTROPY_SRC_HT_WATERMARK_REG_OFFSET);
367
368 ptrdiff_t high_fails_reg_offset = -1;
369 ptrdiff_t low_fails_reg_offset = -1;
370 for (uint32_t i = 0; i < kDifEntropySrcTestNumVariants; ++i) {
371 switch ((dif_entropy_src_test_t)i) {
373 high_fails_reg_offset = ENTROPY_SRC_REPCNT_TOTAL_FAILS_REG_OFFSET;
374 low_fails_reg_offset = -1;
375 break;
377 high_fails_reg_offset = ENTROPY_SRC_REPCNTS_TOTAL_FAILS_REG_OFFSET;
378 low_fails_reg_offset = -1;
379 break;
381 high_fails_reg_offset = ENTROPY_SRC_ADAPTP_HI_TOTAL_FAILS_REG_OFFSET;
382 low_fails_reg_offset = ENTROPY_SRC_ADAPTP_LO_TOTAL_FAILS_REG_OFFSET;
383 break;
385 high_fails_reg_offset = ENTROPY_SRC_BUCKET_TOTAL_FAILS_REG_OFFSET;
386 low_fails_reg_offset = -1;
387 break;
389 high_fails_reg_offset = ENTROPY_SRC_MARKOV_HI_TOTAL_FAILS_REG_OFFSET;
390 low_fails_reg_offset = ENTROPY_SRC_MARKOV_LO_TOTAL_FAILS_REG_OFFSET;
391 break;
393 high_fails_reg_offset = ENTROPY_SRC_EXTHT_HI_TOTAL_FAILS_REG_OFFSET;
394 low_fails_reg_offset = ENTROPY_SRC_EXTHT_LO_TOTAL_FAILS_REG_OFFSET;
395 break;
396 default:
397 return kDifError;
398 }
399
400 stats->high_fails[i] =
401 mmio_region_read32(entropy_src->base_addr, high_fails_reg_offset);
402 stats->low_fails[i] =
403 low_fails_reg_offset == -1
404 ? 0
405 : mmio_region_read32(entropy_src->base_addr, low_fails_reg_offset);
406 }
407
408 return kDifOk;
409}
410
411dif_result_t dif_entropy_src_get_alert_fail_counts(
412 const dif_entropy_src_t *entropy_src,
414 if (entropy_src == NULL || counts == NULL) {
415 return kDifBadArg;
416 }
417
418 counts->total_fails = (uint16_t)mmio_region_read32(
419 entropy_src->base_addr, ENTROPY_SRC_ALERT_SUMMARY_FAIL_COUNTS_REG_OFFSET);
420
421 uint32_t alert_fail_counts = mmio_region_read32(
422 entropy_src->base_addr, ENTROPY_SRC_ALERT_FAIL_COUNTS_REG_OFFSET);
423 uint32_t extht_alert_fail_counts = mmio_region_read32(
424 entropy_src->base_addr, ENTROPY_SRC_EXTHT_FAIL_COUNTS_REG_OFFSET);
425
426 // Unpack high threshold failure counts.
428 (uint8_t)bitfield_field32_read(
429 alert_fail_counts,
430 ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNT_FAIL_COUNT_FIELD);
432 (uint8_t)bitfield_field32_read(
433 alert_fail_counts,
434 ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNTS_FAIL_COUNT_FIELD);
436 (uint8_t)bitfield_field32_read(
437 alert_fail_counts,
438 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_HI_FAIL_COUNT_FIELD);
439 counts->high_fails[kDifEntropySrcTestBucket] = (uint8_t)bitfield_field32_read(
440 alert_fail_counts, ENTROPY_SRC_ALERT_FAIL_COUNTS_BUCKET_FAIL_COUNT_FIELD);
441 counts->high_fails[kDifEntropySrcTestMarkov] = (uint8_t)bitfield_field32_read(
442 alert_fail_counts,
443 ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_HI_FAIL_COUNT_FIELD);
445 (uint8_t)bitfield_field32_read(
446 extht_alert_fail_counts,
447 ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_HI_FAIL_COUNT_FIELD);
448
449 // Unpack low threshold failure counts.
453 (uint8_t)bitfield_field32_read(
454 alert_fail_counts,
455 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_LO_FAIL_COUNT_FIELD);
457 counts->low_fails[kDifEntropySrcTestMarkov] = (uint8_t)bitfield_field32_read(
458 alert_fail_counts,
459 ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_LO_FAIL_COUNT_FIELD);
460 counts->low_fails[kDifEntropySrcTestMailbox] = (uint8_t)bitfield_field32_read(
461 extht_alert_fail_counts,
462 ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_LO_FAIL_COUNT_FIELD);
463
464 return kDifOk;
465}
466
467static bool is_entropy_available(const dif_entropy_src_t *entropy_src) {
468 return mmio_region_get_bit32(entropy_src->base_addr,
469 ENTROPY_SRC_INTR_STATE_REG_OFFSET,
470 ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
471}
472
473dif_result_t dif_entropy_src_is_entropy_available(
474 const dif_entropy_src_t *entropy_src) {
475 if (entropy_src == NULL) {
476 return kDifBadArg;
477 }
478
479 return is_entropy_available(entropy_src) ? kDifOk : kDifUnavailable;
480}
481
482dif_result_t dif_entropy_src_non_blocking_read(
483 const dif_entropy_src_t *entropy_src, uint32_t *word) {
484 if (entropy_src == NULL || word == NULL) {
485 return kDifBadArg;
486 }
487
488 // Check if entropy is available.
489 if (!is_entropy_available(entropy_src)) {
490 return kDifUnavailable;
491 }
492
493 *word = mmio_region_read32(entropy_src->base_addr,
494 ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET);
495
496 // Clear interrupt state after fetching read if there is still entropy
497 // available, the interrupt state will set again.
498 mmio_region_nonatomic_set_bit32(entropy_src->base_addr,
499 ENTROPY_SRC_INTR_STATE_REG_OFFSET,
500 ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
501
502 return kDifOk;
503}
504
505dif_result_t dif_entropy_src_observe_fifo_blocking_read(
506 const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t len) {
507 if (entropy_src == NULL) {
508 return kDifBadArg;
509 }
510
511 // Check that the number of bytes to be read is less than or equal to the FIFO
512 // threshold that triggers an interrupt.
513 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
514 ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET);
515 if (len > reg) {
516 return kDifBadArg;
517 }
518
519 // Check that we are in firmware override mode. We can only read from the
520 // observe FIFO if we are.
521 reg = mmio_region_read32(entropy_src->base_addr,
522 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
523 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
524 kMultiBitBool4True) {
525 return kDifError;
526 }
527
528 // Block until there is enough data in the observe FIFO.
529 do {
530 reg = mmio_region_read32(entropy_src->base_addr,
531 ENTROPY_SRC_INTR_STATE_REG_OFFSET);
532 } while (!bitfield_bit32_read(
533 reg, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT));
534
535 // Read post-health test, pre-conditioned, entropy from the observe FIFO.
536 for (size_t i = 0; i < len; ++i) {
537 reg = mmio_region_read32(entropy_src->base_addr,
538 ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
539 if (buf != NULL) {
540 buf[i] = reg;
541 }
542 }
543
544 // Clear the status bit.
545 reg = bitfield_bit32_write(
546 0, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT, true);
547 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_INTR_STATE_REG_OFFSET,
548 reg);
549
550 return kDifOk;
551}
552
553dif_result_t dif_entropy_src_observe_fifo_nonblocking_read(
554 const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t *len) {
555 if (entropy_src == NULL || len == NULL) {
556 return kDifBadArg;
557 }
558
559 // Check that we are in firmware override mode. We can only read from the
560 // observe FIFO if we are.
561 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
562 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
563 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
564 kMultiBitBool4True) {
565 return kDifError;
566 }
567
568 // Read until FIFO is empty or we have read `*len` words.
569 size_t read_count = 0;
570 while (read_count < *len &&
571 mmio_region_read32(entropy_src->base_addr,
572 ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET) > 0) {
573 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
574 ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
575 if (buf != NULL) {
576 buf[read_count++] = reg;
577 }
578 }
579 // Update `*len`.
580 *len = read_count;
581
582 return kDifOk;
583}
584
585dif_result_t dif_entropy_src_fw_ov_data_write(
586 const dif_entropy_src_t *entropy_src, const uint32_t *buf, size_t len,
587 size_t *written) {
588 if (entropy_src == NULL || buf == NULL) {
589 return kDifBadArg;
590 }
591
592 // Check that we are in firmware override mode and that we can insert data
593 // into the entropy pipeline.
594 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
595 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
596 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
597 kMultiBitBool4True ||
598 bitfield_field32_read(
599 reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_FIELD) !=
600 kMultiBitBool4True) {
601 return kDifError;
602 }
603
604 // Check if the FIFO is full before writing each word.
605 for (size_t i = 0; i < len; ++i) {
606 if (mmio_region_read32(entropy_src->base_addr,
607 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
608 if (written) {
609 *written = i;
610 }
611 return kDifIpFifoFull;
612 }
613
614 mmio_region_write32(entropy_src->base_addr,
615 ENTROPY_SRC_FW_OV_WR_DATA_REG_OFFSET, buf[i]);
616 }
617
618 if (written) {
619 *written = len;
620 }
621 return kDifOk;
622}
623
624dif_result_t dif_entropy_src_conditioner_start(
625 const dif_entropy_src_t *entropy_src) {
626 if (entropy_src == NULL) {
627 return kDifBadArg;
628 }
629
630 // Check if SHA3 conditioner operation has already started.
631 uint32_t current_val = mmio_region_read32(
632 entropy_src->base_addr, ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET);
633 if (current_val == kMultiBitBool4True) {
634 return kDifUnavailable;
635 }
636
637 mmio_region_write32(entropy_src->base_addr,
638 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
639 kMultiBitBool4True);
640
641 return kDifOk;
642}
643
644dif_result_t dif_entropy_src_conditioner_stop(
645 const dif_entropy_src_t *entropy_src) {
646 if (entropy_src == NULL) {
647 return kDifBadArg;
648 }
649
650 // Check the FW_OV_WR_FIFO_FULL register to determine in any data is
651 // stalling at the input of the SHA3 conditioner.
652 if (mmio_region_read32(entropy_src->base_addr,
653 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
654 return kDifIpFifoFull;
655 }
656
657 mmio_region_write32(entropy_src->base_addr,
658 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
659 kMultiBitBool4False);
660 return kDifOk;
661}
662
663dif_result_t dif_entropy_src_is_fifo_full(const dif_entropy_src_t *entropy_src,
664 bool *is_full) {
665 if (entropy_src == NULL || is_full == NULL) {
666 return kDifBadArg;
667 }
668
669 *is_full = mmio_region_read32(entropy_src->base_addr,
670 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET);
671
672 return kDifOk;
673}
674
675dif_result_t dif_entropy_src_has_fifo_overflowed(
676 const dif_entropy_src_t *entropy_src, bool *has_overflowed) {
677 if (entropy_src == NULL || has_overflowed == NULL) {
678 return kDifBadArg;
679 }
680
681 *has_overflowed = mmio_region_read32(
682 entropy_src->base_addr, ENTROPY_SRC_FW_OV_RD_FIFO_OVERFLOW_REG_OFFSET);
683
684 return kDifOk;
685}
686
687dif_result_t dif_entropy_src_get_fifo_depth(
688 const dif_entropy_src_t *entropy_src, uint32_t *fifo_depth) {
689 if (entropy_src == NULL || fifo_depth == NULL) {
690 return kDifBadArg;
691 }
692
693 *fifo_depth = mmio_region_read32(entropy_src->base_addr,
694 ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET);
695
696 return kDifOk;
697}
698
699dif_result_t dif_entropy_src_get_debug_state(
700 const dif_entropy_src_t *entropy_src,
701 dif_entropy_src_debug_state_t *debug_state) {
702 if (entropy_src == NULL || debug_state == NULL) {
703 return kDifBadArg;
704 }
705
706 uint32_t debug_state_reg = mmio_region_read32(
707 entropy_src->base_addr, ENTROPY_SRC_DEBUG_STATUS_REG_OFFSET);
708 debug_state->entropy_fifo_depth = (uint8_t)bitfield_field32_read(
709 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_ENTROPY_FIFO_DEPTH_FIELD);
710 debug_state->sha3_fsm_state = bitfield_field32_read(
711 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_FSM_FIELD);
712 debug_state->sha3_block_processed = bitfield_bit32_read(
713 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_BLOCK_PR_BIT);
714 debug_state->sha3_squeezing = bitfield_bit32_read(
715 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_SQUEEZING_BIT);
716 debug_state->sha3_absorbed = bitfield_bit32_read(
717 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ABSORBED_BIT);
718 debug_state->sha3_error = bitfield_bit32_read(
719 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ERR_BIT);
720 debug_state->main_fsm_is_idle = bitfield_bit32_read(
721 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_IDLE_BIT);
722 debug_state->main_fsm_boot_done = bitfield_bit32_read(
723 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_BOOT_DONE_BIT);
724
725 return kDifOk;
726}
727
728dif_result_t dif_entropy_src_get_recoverable_alerts(
729 const dif_entropy_src_t *entropy_src, uint32_t *alerts) {
730 if (entropy_src == NULL || alerts == NULL) {
731 return kDifBadArg;
732 }
733
734 *alerts = mmio_region_read32(entropy_src->base_addr,
735 ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
736
737 return kDifOk;
738}
739
740dif_result_t dif_entropy_src_clear_recoverable_alerts(
741 const dif_entropy_src_t *entropy_src, uint32_t alerts) {
742 if (entropy_src == NULL || alerts > kDifEntropySrcAlertAllAlerts) {
743 return kDifBadArg;
744 }
745
746 uint32_t active_alerts = mmio_region_read32(
747 entropy_src->base_addr, ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
748 active_alerts &= ~alerts;
749 mmio_region_write32(entropy_src->base_addr,
750 ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET, active_alerts);
751
752 return kDifOk;
753}
754
755dif_result_t dif_entropy_src_get_errors(const dif_entropy_src_t *entropy_src,
756 uint32_t *errors) {
757 if (entropy_src == NULL || errors == NULL) {
758 return kDifBadArg;
759 }
760
761 uint32_t err_code_reg = mmio_region_read32(entropy_src->base_addr,
762 ENTROPY_SRC_ERR_CODE_REG_OFFSET);
763
764 *errors = 0;
765
766 // ESRNG FIFO errors.
767 if (bitfield_bit32_read(err_code_reg,
768 ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT)) {
769 if (bitfield_bit32_read(err_code_reg,
770 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
772 }
773 if (bitfield_bit32_read(err_code_reg,
774 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
776 }
777 if (bitfield_bit32_read(err_code_reg,
778 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
780 }
781 }
782
783 // Observe FIFO errors.
784 if (bitfield_bit32_read(err_code_reg,
785 ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT)) {
786 if (bitfield_bit32_read(err_code_reg,
787 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
789 }
790 if (bitfield_bit32_read(err_code_reg,
791 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
793 }
794 if (bitfield_bit32_read(err_code_reg,
795 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
797 }
798 }
799
800 // ESFINAL FIFO errors.
801 if (bitfield_bit32_read(err_code_reg,
802 ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT)) {
803 if (bitfield_bit32_read(err_code_reg,
804 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
806 }
807 if (bitfield_bit32_read(err_code_reg,
808 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
810 }
811 if (bitfield_bit32_read(err_code_reg,
812 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
814 }
815 }
816
817 // Remaining FSM/Counter errors.
818 if (bitfield_bit32_read(err_code_reg,
819 ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT)) {
821 }
822 if (bitfield_bit32_read(err_code_reg,
823 ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT)) {
825 }
826 if (bitfield_bit32_read(err_code_reg, ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT)) {
828 }
829
830 return kDifOk;
831}
832
833dif_result_t dif_entropy_src_error_force(const dif_entropy_src_t *entropy_src,
835 if (entropy_src == NULL) {
836 return kDifBadArg;
837 }
838
839 uint32_t err_code_reg = 0;
840
841 switch (error) {
845 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT;
846 break;
850 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT;
851 break;
855 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT;
856 break;
858 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT;
859 break;
861 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT;
862 break;
864 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT;
865 break;
866 default:
867 return kDifBadArg;
868 }
869
870 mmio_region_write32(entropy_src->base_addr,
871 ENTROPY_SRC_ERR_CODE_TEST_REG_OFFSET, err_code_reg);
872
873 return kDifOk;
874}
875
876dif_result_t dif_entropy_src_get_main_fsm_state(
877 const dif_entropy_src_t *entropy_src, dif_entropy_src_main_fsm_t *state) {
878 if (entropy_src == NULL || state == NULL) {
879 return kDifBadArg;
880 }
881
882 *state = mmio_region_read32(entropy_src->base_addr,
883 ENTROPY_SRC_MAIN_SM_STATE_REG_OFFSET);
884
885 return kDifOk;
886}