1 /*
2  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <mmio.h>
9 #include <string.h>
10 #include <utils_def.h>
11 #include "juno_def.h"
12 
13 #define NSAMPLE_CLOCKS	1 /* min 1 cycle, max 231 cycles */
14 #define NRETRIES	5
15 
output_valid(void)16 static inline int output_valid(void)
17 {
18 	int i;
19 
20 	for (i = 0; i < NRETRIES; i++) {
21 		uint32_t val;
22 
23 		val = mmio_read_32(TRNG_BASE + TRNG_STATUS);
24 		if (val & 1U)
25 			break;
26 	}
27 	if (i >= NRETRIES)
28 		return 0; /* No output data available. */
29 	return 1;
30 }
31 
32 /*
33  * This function fills `buf` with `len` bytes of entropy.
34  * It uses the Trusted Entropy Source peripheral on Juno.
35  * Returns 0 when the buffer has been filled with entropy
36  * successfully and -1 otherwise.
37  */
juno_getentropy(void * buf,size_t len)38 int juno_getentropy(void *buf, size_t len)
39 {
40 	uint8_t *bp = buf;
41 
42 	assert(buf);
43 	assert(len);
44 	assert(!check_uptr_overflow((uintptr_t)bp, len));
45 
46 	/* Disable interrupt mode. */
47 	mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0);
48 	/* Program TRNG to sample for `NSAMPLE_CLOCKS`. */
49 	mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS);
50 
51 	while (len > 0) {
52 		int i;
53 
54 		/* Start TRNG. */
55 		mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1);
56 
57 		/* Check if output is valid. */
58 		if (!output_valid())
59 			return -1;
60 
61 		/* Fill entropy buffer. */
62 		for (i = 0; i < TRNG_NOUTPUTS; i++) {
63 			size_t n;
64 			uint32_t val;
65 
66 			val = mmio_read_32(TRNG_BASE + i * sizeof(uint32_t));
67 			n = MIN(len, sizeof(uint32_t));
68 			memcpy(bp, &val, n);
69 			bp += n;
70 			len -= n;
71 			if (len == 0)
72 				break;
73 		}
74 
75 		/* Reset TRNG outputs. */
76 		mmio_write_32(TRNG_BASE + TRNG_STATUS, 1);
77 	}
78 
79 	return 0;
80 }
81