xref: /rk3399_ARM-atf/plat/arm/board/juno/juno_trng.c (revision df9a39eaa956a42020f436d4fe5fb47d5ae793d0)
1*df9a39eaSdp-arm /*
2*df9a39eaSdp-arm  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3*df9a39eaSdp-arm  *
4*df9a39eaSdp-arm  * Redistribution and use in source and binary forms, with or without
5*df9a39eaSdp-arm  * modification, are permitted provided that the following conditions are met:
6*df9a39eaSdp-arm  *
7*df9a39eaSdp-arm  * Redistributions of source code must retain the above copyright notice, this
8*df9a39eaSdp-arm  * list of conditions and the following disclaimer.
9*df9a39eaSdp-arm  *
10*df9a39eaSdp-arm  * Redistributions in binary form must reproduce the above copyright notice,
11*df9a39eaSdp-arm  * this list of conditions and the following disclaimer in the documentation
12*df9a39eaSdp-arm  * and/or other materials provided with the distribution.
13*df9a39eaSdp-arm  *
14*df9a39eaSdp-arm  * Neither the name of ARM nor the names of its contributors may be used
15*df9a39eaSdp-arm  * to endorse or promote products derived from this software without specific
16*df9a39eaSdp-arm  * prior written permission.
17*df9a39eaSdp-arm  *
18*df9a39eaSdp-arm  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*df9a39eaSdp-arm  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*df9a39eaSdp-arm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*df9a39eaSdp-arm  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*df9a39eaSdp-arm  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*df9a39eaSdp-arm  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*df9a39eaSdp-arm  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*df9a39eaSdp-arm  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*df9a39eaSdp-arm  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*df9a39eaSdp-arm  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*df9a39eaSdp-arm  * POSSIBILITY OF SUCH DAMAGE.
29*df9a39eaSdp-arm  */
30*df9a39eaSdp-arm 
31*df9a39eaSdp-arm #include <assert.h>
32*df9a39eaSdp-arm #include <mmio.h>
33*df9a39eaSdp-arm #include <string.h>
34*df9a39eaSdp-arm #include <utils.h>
35*df9a39eaSdp-arm #include "juno_def.h"
36*df9a39eaSdp-arm 
37*df9a39eaSdp-arm #define NSAMPLE_CLOCKS	1 /* min 1 cycle, max 231 cycles */
38*df9a39eaSdp-arm #define NRETRIES	5
39*df9a39eaSdp-arm 
40*df9a39eaSdp-arm static inline int output_valid(void)
41*df9a39eaSdp-arm {
42*df9a39eaSdp-arm 	int i;
43*df9a39eaSdp-arm 
44*df9a39eaSdp-arm 	for (i = 0; i < NRETRIES; i++) {
45*df9a39eaSdp-arm 		uint32_t val;
46*df9a39eaSdp-arm 
47*df9a39eaSdp-arm 		val = mmio_read_32(TRNG_BASE + TRNG_STATUS);
48*df9a39eaSdp-arm 		if (val & 1U)
49*df9a39eaSdp-arm 			break;
50*df9a39eaSdp-arm 	}
51*df9a39eaSdp-arm 	if (i >= NRETRIES)
52*df9a39eaSdp-arm 		return 0; /* No output data available. */
53*df9a39eaSdp-arm 	return 1;
54*df9a39eaSdp-arm }
55*df9a39eaSdp-arm 
56*df9a39eaSdp-arm /*
57*df9a39eaSdp-arm  * This function fills `buf` with `len` bytes of entropy.
58*df9a39eaSdp-arm  * It uses the Trusted Entropy Source peripheral on Juno.
59*df9a39eaSdp-arm  * Returns 0 when the buffer has been filled with entropy
60*df9a39eaSdp-arm  * successfully and -1 otherwise.
61*df9a39eaSdp-arm  */
62*df9a39eaSdp-arm int juno_getentropy(void *buf, size_t len)
63*df9a39eaSdp-arm {
64*df9a39eaSdp-arm 	uint8_t *bp = buf;
65*df9a39eaSdp-arm 
66*df9a39eaSdp-arm 	assert(buf);
67*df9a39eaSdp-arm 	assert(len);
68*df9a39eaSdp-arm 	assert(!check_uptr_overflow((uintptr_t)bp, len));
69*df9a39eaSdp-arm 
70*df9a39eaSdp-arm 	/* Disable interrupt mode. */
71*df9a39eaSdp-arm 	mmio_write_32(TRNG_BASE + TRNG_INTMASK, 0);
72*df9a39eaSdp-arm 	/* Program TRNG to sample for `NSAMPLE_CLOCKS`. */
73*df9a39eaSdp-arm 	mmio_write_32(TRNG_BASE + TRNG_CONFIG, NSAMPLE_CLOCKS);
74*df9a39eaSdp-arm 
75*df9a39eaSdp-arm 	while (len > 0) {
76*df9a39eaSdp-arm 		int i;
77*df9a39eaSdp-arm 
78*df9a39eaSdp-arm 		/* Start TRNG. */
79*df9a39eaSdp-arm 		mmio_write_32(TRNG_BASE + TRNG_CONTROL, 1);
80*df9a39eaSdp-arm 
81*df9a39eaSdp-arm 		/* Check if output is valid. */
82*df9a39eaSdp-arm 		if (!output_valid())
83*df9a39eaSdp-arm 			return -1;
84*df9a39eaSdp-arm 
85*df9a39eaSdp-arm 		/* Fill entropy buffer. */
86*df9a39eaSdp-arm 		for (i = 0; i < TRNG_NOUTPUTS; i++) {
87*df9a39eaSdp-arm 			size_t n;
88*df9a39eaSdp-arm 			uint32_t val;
89*df9a39eaSdp-arm 
90*df9a39eaSdp-arm 			val = mmio_read_32(TRNG_BASE + i * sizeof(uint32_t));
91*df9a39eaSdp-arm 			n = MIN(len, sizeof(uint32_t));
92*df9a39eaSdp-arm 			memcpy(bp, &val, n);
93*df9a39eaSdp-arm 			bp += n;
94*df9a39eaSdp-arm 			len -= n;
95*df9a39eaSdp-arm 			if (len == 0)
96*df9a39eaSdp-arm 				break;
97*df9a39eaSdp-arm 		}
98*df9a39eaSdp-arm 
99*df9a39eaSdp-arm 		/* Reset TRNG outputs. */
100*df9a39eaSdp-arm 		mmio_write_32(TRNG_BASE + TRNG_STATUS, 1);
101*df9a39eaSdp-arm 	}
102*df9a39eaSdp-arm 
103*df9a39eaSdp-arm 	return 0;
104*df9a39eaSdp-arm }
105