blob: d9ad1d4eb950d9e00c31fd8f5ae402aa53443474 [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>
8#include <mmio.h>
9#include <string.h>
Scott Brandenbf404c02017-04-10 11:45:52 -070010#include <utils_def.h>
Roberto Vargas2b36b152018-02-12 12:36:17 +000011#include "juno_decl.h"
dp-arm8f59e152017-02-27 12:21:43 +000012#include "juno_def.h"
13
14#define NSAMPLE_CLOCKS 1 /* min 1 cycle, max 231 cycles */
15#define NRETRIES 5
16
17static 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 */
39int 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}