blob: 124821b8d3251cab079aef0aa6e58dae8eda3c3f [file] [log] [blame]
dp-arm8f59e152017-02-27 12:21:43 +00001/*
2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3 *
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>
8#include <mmio.h>
9#include <string.h>
Scott Brandenbf404c02017-04-10 11:45:52 -070010#include <utils_def.h>
dp-arm8f59e152017-02-27 12:21:43 +000011#include "juno_def.h"
12
13#define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */
14#define NRETRIES 5
15
16static 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 */
38int 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}