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 "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 ~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_thresholds_reg_offset = -1;
214 ptrdiff_t low_thresholds_reg_offset = -1;
215 switch (config.test_type) {
217 high_thresholds_reg_offset = ENTROPY_SRC_REPCNT_THRESHOLDS_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_thresholds_reg_offset = ENTROPY_SRC_REPCNTS_THRESHOLDS_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_thresholds_reg_offset = ENTROPY_SRC_ADAPTP_HI_THRESHOLDS_REG_OFFSET;
232 low_thresholds_reg_offset = ENTROPY_SRC_ADAPTP_LO_THRESHOLDS_REG_OFFSET;
233 break;
235 high_thresholds_reg_offset = ENTROPY_SRC_BUCKET_THRESHOLDS_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_thresholds_reg_offset = ENTROPY_SRC_MARKOV_HI_THRESHOLDS_REG_OFFSET;
243 low_thresholds_reg_offset = ENTROPY_SRC_MARKOV_LO_THRESHOLDS_REG_OFFSET;
244 break;
246 high_thresholds_reg_offset = ENTROPY_SRC_EXTHT_HI_THRESHOLDS_REG_OFFSET;
247 low_thresholds_reg_offset = ENTROPY_SRC_EXTHT_LO_THRESHOLDS_REG_OFFSET;
248 break;
249 default:
250 return kDifBadArg;
251 }
252
253 mmio_region_write32(entropy_src->base_addr, high_thresholds_reg_offset,
254 config.high_threshold);
255 if (low_thresholds_reg_offset != -1) {
256 mmio_region_write32(entropy_src->base_addr, low_thresholds_reg_offset,
257 config.low_threshold);
258 }
259
260 return kDifOk;
261}
262
263dif_result_t dif_entropy_src_set_enabled(const dif_entropy_src_t *entropy_src,
264 dif_toggle_t enabled) {
265 if (entropy_src == NULL || !dif_is_valid_toggle(enabled)) {
266 return kDifBadArg;
267 }
268
269 if (!mmio_region_read32(entropy_src->base_addr,
270 ENTROPY_SRC_ME_REGWEN_REG_OFFSET)) {
271 return kDifLocked;
272 }
273
274 mmio_region_write32(entropy_src->base_addr,
275 ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
276 dif_toggle_to_multi_bit_bool4(enabled));
277
278 return kDifOk;
279}
280
281dif_result_t dif_entropy_src_lock(const dif_entropy_src_t *entropy_src) {
282 if (entropy_src == NULL) {
283 return kDifBadArg;
284 }
285
286 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET,
287 0);
288 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_SW_REGUPD_REG_OFFSET,
289 0);
290
291 return kDifOk;
292}
293
294dif_result_t dif_entropy_src_is_locked(const dif_entropy_src_t *entropy_src,
295 bool *is_locked) {
296 if (entropy_src == NULL || is_locked == NULL) {
297 return kDifBadArg;
298 }
299
300 uint32_t module_enable_regwen = mmio_region_read32(
301 entropy_src->base_addr, ENTROPY_SRC_ME_REGWEN_REG_OFFSET);
302 uint32_t sw_regupd = mmio_region_read32(entropy_src->base_addr,
303 ENTROPY_SRC_SW_REGUPD_REG_OFFSET);
304 if (module_enable_regwen == sw_regupd) {
305 *is_locked = sw_regupd == 0;
306 } else {
307 // Since we actuate these together, either both should be 0 (locked), or
308 // both should be 1 (unlocked). If only one is locked, then we have
309 // gotten into a bad state.
310 return kDifError;
311 }
312
313 return kDifOk;
314}
315
316dif_result_t dif_entropy_src_get_health_test_stats(
317 const dif_entropy_src_t *entropy_src,
319 if (entropy_src == NULL || stats == NULL) {
320 return kDifBadArg;
321 }
322
323 ptrdiff_t high_watermarks_reg_offset = -1;
324 ptrdiff_t low_watermarks_reg_offset = -1;
325 ptrdiff_t high_fails_reg_offset = -1;
326 ptrdiff_t low_fails_reg_offset = -1;
327 for (uint32_t i = 0; i < kDifEntropySrcTestNumVariants; ++i) {
328 switch ((dif_entropy_src_test_t)i) {
330 high_watermarks_reg_offset =
331 ENTROPY_SRC_REPCNT_HI_WATERMARKS_REG_OFFSET;
332 low_watermarks_reg_offset = -1;
333 high_fails_reg_offset = ENTROPY_SRC_REPCNT_TOTAL_FAILS_REG_OFFSET;
334 low_fails_reg_offset = -1;
335 break;
337 high_watermarks_reg_offset =
338 ENTROPY_SRC_REPCNTS_HI_WATERMARKS_REG_OFFSET;
339 low_watermarks_reg_offset = -1;
340 high_fails_reg_offset = ENTROPY_SRC_REPCNTS_TOTAL_FAILS_REG_OFFSET;
341 low_fails_reg_offset = -1;
342 break;
344 high_watermarks_reg_offset =
345 ENTROPY_SRC_ADAPTP_HI_WATERMARKS_REG_OFFSET;
346 low_watermarks_reg_offset = ENTROPY_SRC_ADAPTP_LO_WATERMARKS_REG_OFFSET;
347 high_fails_reg_offset = ENTROPY_SRC_ADAPTP_HI_TOTAL_FAILS_REG_OFFSET;
348 low_fails_reg_offset = ENTROPY_SRC_ADAPTP_LO_TOTAL_FAILS_REG_OFFSET;
349 break;
351 high_watermarks_reg_offset =
352 ENTROPY_SRC_BUCKET_HI_WATERMARKS_REG_OFFSET;
353 low_watermarks_reg_offset = -1;
354 high_fails_reg_offset = ENTROPY_SRC_BUCKET_TOTAL_FAILS_REG_OFFSET;
355 low_fails_reg_offset = -1;
356 break;
358 high_watermarks_reg_offset =
359 ENTROPY_SRC_MARKOV_HI_WATERMARKS_REG_OFFSET;
360 low_watermarks_reg_offset = ENTROPY_SRC_MARKOV_LO_WATERMARKS_REG_OFFSET;
361 high_fails_reg_offset = ENTROPY_SRC_MARKOV_HI_TOTAL_FAILS_REG_OFFSET;
362 low_fails_reg_offset = ENTROPY_SRC_MARKOV_LO_TOTAL_FAILS_REG_OFFSET;
363 break;
365 high_watermarks_reg_offset = ENTROPY_SRC_EXTHT_HI_WATERMARKS_REG_OFFSET;
366 low_watermarks_reg_offset = ENTROPY_SRC_EXTHT_LO_WATERMARKS_REG_OFFSET;
367 high_fails_reg_offset = ENTROPY_SRC_EXTHT_HI_TOTAL_FAILS_REG_OFFSET;
368 low_fails_reg_offset = ENTROPY_SRC_EXTHT_LO_TOTAL_FAILS_REG_OFFSET;
369 break;
370 default:
371 return kDifError;
372 }
373
374 stats->high_watermark[i] = (uint16_t)mmio_region_read32(
375 entropy_src->base_addr, high_watermarks_reg_offset);
376 stats->low_watermark[i] =
377 low_watermarks_reg_offset == -1
378 ? 0
379 : (uint16_t)mmio_region_read32(entropy_src->base_addr,
380 low_watermarks_reg_offset);
381
382 stats->high_fails[i] =
383 mmio_region_read32(entropy_src->base_addr, high_fails_reg_offset);
384 stats->low_fails[i] =
385 low_fails_reg_offset == -1
386 ? 0
387 : mmio_region_read32(entropy_src->base_addr, low_fails_reg_offset);
388 }
389
390 return kDifOk;
391}
392
393dif_result_t dif_entropy_src_get_alert_fail_counts(
394 const dif_entropy_src_t *entropy_src,
396 if (entropy_src == NULL || counts == NULL) {
397 return kDifBadArg;
398 }
399
400 counts->total_fails = (uint16_t)mmio_region_read32(
401 entropy_src->base_addr, ENTROPY_SRC_ALERT_SUMMARY_FAIL_COUNTS_REG_OFFSET);
402
403 uint32_t alert_fail_counts = mmio_region_read32(
404 entropy_src->base_addr, ENTROPY_SRC_ALERT_FAIL_COUNTS_REG_OFFSET);
405 uint32_t extht_alert_fail_counts = mmio_region_read32(
406 entropy_src->base_addr, ENTROPY_SRC_EXTHT_FAIL_COUNTS_REG_OFFSET);
407
408 // Unpack high threshold failure counts.
410 (uint8_t)bitfield_field32_read(
411 alert_fail_counts,
412 ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNT_FAIL_COUNT_FIELD);
414 (uint8_t)bitfield_field32_read(
415 alert_fail_counts,
416 ENTROPY_SRC_ALERT_FAIL_COUNTS_REPCNTS_FAIL_COUNT_FIELD);
418 (uint8_t)bitfield_field32_read(
419 alert_fail_counts,
420 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_HI_FAIL_COUNT_FIELD);
421 counts->high_fails[kDifEntropySrcTestBucket] = (uint8_t)bitfield_field32_read(
422 alert_fail_counts, ENTROPY_SRC_ALERT_FAIL_COUNTS_BUCKET_FAIL_COUNT_FIELD);
423 counts->high_fails[kDifEntropySrcTestMarkov] = (uint8_t)bitfield_field32_read(
424 alert_fail_counts,
425 ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_HI_FAIL_COUNT_FIELD);
427 (uint8_t)bitfield_field32_read(
428 extht_alert_fail_counts,
429 ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_HI_FAIL_COUNT_FIELD);
430
431 // Unpack low threshold failure counts.
435 (uint8_t)bitfield_field32_read(
436 alert_fail_counts,
437 ENTROPY_SRC_ALERT_FAIL_COUNTS_ADAPTP_LO_FAIL_COUNT_FIELD);
439 counts->low_fails[kDifEntropySrcTestMarkov] = (uint8_t)bitfield_field32_read(
440 alert_fail_counts,
441 ENTROPY_SRC_ALERT_FAIL_COUNTS_MARKOV_LO_FAIL_COUNT_FIELD);
442 counts->low_fails[kDifEntropySrcTestMailbox] = (uint8_t)bitfield_field32_read(
443 extht_alert_fail_counts,
444 ENTROPY_SRC_EXTHT_FAIL_COUNTS_EXTHT_LO_FAIL_COUNT_FIELD);
445
446 return kDifOk;
447}
448
449static bool is_entropy_available(const dif_entropy_src_t *entropy_src) {
450 return mmio_region_get_bit32(entropy_src->base_addr,
451 ENTROPY_SRC_INTR_STATE_REG_OFFSET,
452 ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
453}
454
455dif_result_t dif_entropy_src_is_entropy_available(
456 const dif_entropy_src_t *entropy_src) {
457 if (entropy_src == NULL) {
458 return kDifBadArg;
459 }
460
461 return is_entropy_available(entropy_src) ? kDifOk : kDifUnavailable;
462}
463
464dif_result_t dif_entropy_src_non_blocking_read(
465 const dif_entropy_src_t *entropy_src, uint32_t *word) {
466 if (entropy_src == NULL || word == NULL) {
467 return kDifBadArg;
468 }
469
470 // Check if entropy is available.
471 if (!is_entropy_available(entropy_src)) {
472 return kDifUnavailable;
473 }
474
475 *word = mmio_region_read32(entropy_src->base_addr,
476 ENTROPY_SRC_ENTROPY_DATA_REG_OFFSET);
477
478 // Clear interrupt state after fetching read if there is still entropy
479 // available, the interrupt state will set again.
480 mmio_region_nonatomic_set_bit32(entropy_src->base_addr,
481 ENTROPY_SRC_INTR_STATE_REG_OFFSET,
482 ENTROPY_SRC_INTR_STATE_ES_ENTROPY_VALID_BIT);
483
484 return kDifOk;
485}
486
487dif_result_t dif_entropy_src_observe_fifo_blocking_read(
488 const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t len) {
489 if (entropy_src == NULL) {
490 return kDifBadArg;
491 }
492
493 // Check that the number of bytes to be read is less than or equal to the FIFO
494 // threshold that triggers an interrupt.
495 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
496 ENTROPY_SRC_OBSERVE_FIFO_THRESH_REG_OFFSET);
497 if (len > reg) {
498 return kDifBadArg;
499 }
500
501 // Check that we are in firmware override mode. We can only read from the
502 // observe FIFO if we are.
503 reg = mmio_region_read32(entropy_src->base_addr,
504 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
505 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
506 kMultiBitBool4True) {
507 return kDifError;
508 }
509
510 // Block until there is enough data in the observe FIFO.
511 do {
512 reg = mmio_region_read32(entropy_src->base_addr,
513 ENTROPY_SRC_INTR_STATE_REG_OFFSET);
514 } while (!bitfield_bit32_read(
515 reg, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT));
516
517 // Read post-health test, pre-conditioned, entropy from the observe FIFO.
518 for (size_t i = 0; i < len; ++i) {
519 reg = mmio_region_read32(entropy_src->base_addr,
520 ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
521 if (buf != NULL) {
522 buf[i] = reg;
523 }
524 }
525
526 // Clear the status bit.
527 reg = bitfield_bit32_write(
528 0, ENTROPY_SRC_INTR_STATE_ES_OBSERVE_FIFO_READY_BIT, true);
529 mmio_region_write32(entropy_src->base_addr, ENTROPY_SRC_INTR_STATE_REG_OFFSET,
530 reg);
531
532 return kDifOk;
533}
534
535dif_result_t dif_entropy_src_observe_fifo_nonblocking_read(
536 const dif_entropy_src_t *entropy_src, uint32_t *buf, size_t *len) {
537 if (entropy_src == NULL || len == NULL) {
538 return kDifBadArg;
539 }
540
541 // Check that we are in firmware override mode. We can only read from the
542 // observe FIFO if we are.
543 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
544 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
545 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
546 kMultiBitBool4True) {
547 return kDifError;
548 }
549
550 // Read until FIFO is empty or we have read `*len` words.
551 size_t read_count = 0;
552 while (read_count < *len &&
553 mmio_region_read32(entropy_src->base_addr,
554 ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET) > 0) {
555 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
556 ENTROPY_SRC_FW_OV_RD_DATA_REG_OFFSET);
557 if (buf != NULL) {
558 buf[read_count++] = reg;
559 }
560 }
561 // Update `*len`.
562 *len = read_count;
563
564 return kDifOk;
565}
566
567dif_result_t dif_entropy_src_fw_ov_data_write(
568 const dif_entropy_src_t *entropy_src, const uint32_t *buf, size_t len,
569 size_t *written) {
570 if (entropy_src == NULL || buf == NULL) {
571 return kDifBadArg;
572 }
573
574 // Check that we are in firmware override mode and that we can insert data
575 // into the entropy pipeline.
576 uint32_t reg = mmio_region_read32(entropy_src->base_addr,
577 ENTROPY_SRC_FW_OV_CONTROL_REG_OFFSET);
578 if (bitfield_field32_read(reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_MODE_FIELD) !=
579 kMultiBitBool4True ||
580 bitfield_field32_read(
581 reg, ENTROPY_SRC_FW_OV_CONTROL_FW_OV_ENTROPY_INSERT_FIELD) !=
582 kMultiBitBool4True) {
583 return kDifError;
584 }
585
586 // Check if the FIFO is full before writing each word.
587 for (size_t i = 0; i < len; ++i) {
588 if (mmio_region_read32(entropy_src->base_addr,
589 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
590 if (written) {
591 *written = i;
592 }
593 return kDifIpFifoFull;
594 }
595
596 mmio_region_write32(entropy_src->base_addr,
597 ENTROPY_SRC_FW_OV_WR_DATA_REG_OFFSET, buf[i]);
598 }
599
600 if (written) {
601 *written = len;
602 }
603 return kDifOk;
604}
605
606dif_result_t dif_entropy_src_conditioner_start(
607 const dif_entropy_src_t *entropy_src) {
608 if (entropy_src == NULL) {
609 return kDifBadArg;
610 }
611
612 // Check if SHA3 conditioner operation has already started.
613 uint32_t current_val = mmio_region_read32(
614 entropy_src->base_addr, ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET);
615 if (current_val == kMultiBitBool4True) {
616 return kDifUnavailable;
617 }
618
619 mmio_region_write32(entropy_src->base_addr,
620 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
621 kMultiBitBool4True);
622
623 return kDifOk;
624}
625
626dif_result_t dif_entropy_src_conditioner_stop(
627 const dif_entropy_src_t *entropy_src) {
628 if (entropy_src == NULL) {
629 return kDifBadArg;
630 }
631
632 // Check the FW_OV_WR_FIFO_FULL register to determine in any data is
633 // stalling at the input of the SHA3 conditioner.
634 if (mmio_region_read32(entropy_src->base_addr,
635 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET)) {
636 return kDifIpFifoFull;
637 }
638
639 mmio_region_write32(entropy_src->base_addr,
640 ENTROPY_SRC_FW_OV_SHA3_START_REG_OFFSET,
641 kMultiBitBool4False);
642 return kDifOk;
643}
644
645dif_result_t dif_entropy_src_is_fifo_full(const dif_entropy_src_t *entropy_src,
646 bool *is_full) {
647 if (entropy_src == NULL || is_full == NULL) {
648 return kDifBadArg;
649 }
650
651 *is_full = mmio_region_read32(entropy_src->base_addr,
652 ENTROPY_SRC_FW_OV_WR_FIFO_FULL_REG_OFFSET);
653
654 return kDifOk;
655}
656
657dif_result_t dif_entropy_src_has_fifo_overflowed(
658 const dif_entropy_src_t *entropy_src, bool *has_overflowed) {
659 if (entropy_src == NULL || has_overflowed == NULL) {
660 return kDifBadArg;
661 }
662
663 *has_overflowed = mmio_region_read32(
664 entropy_src->base_addr, ENTROPY_SRC_FW_OV_RD_FIFO_OVERFLOW_REG_OFFSET);
665
666 return kDifOk;
667}
668
669dif_result_t dif_entropy_src_get_fifo_depth(
670 const dif_entropy_src_t *entropy_src, uint32_t *fifo_depth) {
671 if (entropy_src == NULL || fifo_depth == NULL) {
672 return kDifBadArg;
673 }
674
675 *fifo_depth = mmio_region_read32(entropy_src->base_addr,
676 ENTROPY_SRC_OBSERVE_FIFO_DEPTH_REG_OFFSET);
677
678 return kDifOk;
679}
680
681dif_result_t dif_entropy_src_get_debug_state(
682 const dif_entropy_src_t *entropy_src,
683 dif_entropy_src_debug_state_t *debug_state) {
684 if (entropy_src == NULL || debug_state == NULL) {
685 return kDifBadArg;
686 }
687
688 uint32_t debug_state_reg = mmio_region_read32(
689 entropy_src->base_addr, ENTROPY_SRC_DEBUG_STATUS_REG_OFFSET);
690 debug_state->entropy_fifo_depth = (uint8_t)bitfield_field32_read(
691 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_ENTROPY_FIFO_DEPTH_FIELD);
692 debug_state->sha3_fsm_state = bitfield_field32_read(
693 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_FSM_FIELD);
694 debug_state->sha3_block_processed = bitfield_bit32_read(
695 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_BLOCK_PR_BIT);
696 debug_state->sha3_squeezing = bitfield_bit32_read(
697 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_SQUEEZING_BIT);
698 debug_state->sha3_absorbed = bitfield_bit32_read(
699 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ABSORBED_BIT);
700 debug_state->sha3_error = bitfield_bit32_read(
701 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_SHA3_ERR_BIT);
702 debug_state->main_fsm_is_idle = bitfield_bit32_read(
703 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_IDLE_BIT);
704 debug_state->main_fsm_boot_done = bitfield_bit32_read(
705 debug_state_reg, ENTROPY_SRC_DEBUG_STATUS_MAIN_SM_BOOT_DONE_BIT);
706
707 return kDifOk;
708}
709
710dif_result_t dif_entropy_src_get_recoverable_alerts(
711 const dif_entropy_src_t *entropy_src, uint32_t *alerts) {
712 if (entropy_src == NULL || alerts == NULL) {
713 return kDifBadArg;
714 }
715
716 *alerts = mmio_region_read32(entropy_src->base_addr,
717 ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
718
719 return kDifOk;
720}
721
722dif_result_t dif_entropy_src_clear_recoverable_alerts(
723 const dif_entropy_src_t *entropy_src, uint32_t alerts) {
724 if (entropy_src == NULL || alerts > kDifEntropySrcAlertAllAlerts) {
725 return kDifBadArg;
726 }
727
728 uint32_t active_alerts = mmio_region_read32(
729 entropy_src->base_addr, ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET);
730 active_alerts &= ~alerts;
731 mmio_region_write32(entropy_src->base_addr,
732 ENTROPY_SRC_RECOV_ALERT_STS_REG_OFFSET, active_alerts);
733
734 return kDifOk;
735}
736
737dif_result_t dif_entropy_src_get_errors(const dif_entropy_src_t *entropy_src,
738 uint32_t *errors) {
739 if (entropy_src == NULL || errors == NULL) {
740 return kDifBadArg;
741 }
742
743 uint32_t err_code_reg = mmio_region_read32(entropy_src->base_addr,
744 ENTROPY_SRC_ERR_CODE_REG_OFFSET);
745
746 *errors = 0;
747
748 // ESRNG FIFO errors.
749 if (bitfield_bit32_read(err_code_reg,
750 ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT)) {
751 if (bitfield_bit32_read(err_code_reg,
752 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
754 }
755 if (bitfield_bit32_read(err_code_reg,
756 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
758 }
759 if (bitfield_bit32_read(err_code_reg,
760 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
762 }
763 }
764
765 // Observe FIFO errors.
766 if (bitfield_bit32_read(err_code_reg,
767 ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT)) {
768 if (bitfield_bit32_read(err_code_reg,
769 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
771 }
772 if (bitfield_bit32_read(err_code_reg,
773 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
775 }
776 if (bitfield_bit32_read(err_code_reg,
777 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
779 }
780 }
781
782 // ESFINAL FIFO errors.
783 if (bitfield_bit32_read(err_code_reg,
784 ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT)) {
785 if (bitfield_bit32_read(err_code_reg,
786 ENTROPY_SRC_ERR_CODE_FIFO_WRITE_ERR_BIT)) {
788 }
789 if (bitfield_bit32_read(err_code_reg,
790 ENTROPY_SRC_ERR_CODE_FIFO_READ_ERR_BIT)) {
792 }
793 if (bitfield_bit32_read(err_code_reg,
794 ENTROPY_SRC_ERR_CODE_FIFO_STATE_ERR_BIT)) {
796 }
797 }
798
799 // Remaining FSM/Counter errors.
800 if (bitfield_bit32_read(err_code_reg,
801 ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT)) {
803 }
804 if (bitfield_bit32_read(err_code_reg,
805 ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT)) {
807 }
808 if (bitfield_bit32_read(err_code_reg, ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT)) {
810 }
811
812 return kDifOk;
813}
814
815dif_result_t dif_entropy_src_error_force(const dif_entropy_src_t *entropy_src,
817 if (entropy_src == NULL) {
818 return kDifBadArg;
819 }
820
821 uint32_t err_code_reg = 0;
822
823 switch (error) {
827 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESRNG_ERR_BIT;
828 break;
832 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_OBSERVE_ERR_BIT;
833 break;
837 err_code_reg = ENTROPY_SRC_ERR_CODE_SFIFO_ESFINAL_ERR_BIT;
838 break;
840 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_ACK_SM_ERR_BIT;
841 break;
843 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_MAIN_SM_ERR_BIT;
844 break;
846 err_code_reg = ENTROPY_SRC_ERR_CODE_ES_CNTR_ERR_BIT;
847 break;
848 default:
849 return kDifBadArg;
850 }
851
852 mmio_region_write32(entropy_src->base_addr,
853 ENTROPY_SRC_ERR_CODE_TEST_REG_OFFSET, err_code_reg);
854
855 return kDifOk;
856}
857
858dif_result_t dif_entropy_src_get_main_fsm_state(
859 const dif_entropy_src_t *entropy_src, dif_entropy_src_main_fsm_t *state) {
860 if (entropy_src == NULL || state == NULL) {
861 return kDifBadArg;
862 }
863
864 *state = mmio_region_read32(entropy_src->base_addr,
865 ENTROPY_SRC_MAIN_SM_STATE_REG_OFFSET);
866
867 return kDifOk;
868}