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