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