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