1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2014-2016, STMicroelectronics International N.V.
4 */
5
6 #include <io.h>
7 #include <kernel/panic.h>
8 #include <mm/core_mmu.h>
9 #include <mm/core_memprot.h>
10 #include <platform_config.h>
11 #include <trace.h>
12
13 #include "rng_support.h"
14
15 /* Address of the register to read in the RNG IP */
16 #define RNG_VAL_OFFSET 0x24
17 #define RNG_STATUS_OFFSET 0x20
18
19 #define RNG_STATUS_ERR0 BIT32(0)
20 #define RNG_STATUS_ERR1 BIT32(1)
21 #define RNG_STATUS_FULL BIT32(5)
22
rng_base(void)23 static vaddr_t rng_base(void)
24 {
25 static void *va;
26
27 if (cpu_mmu_enabled()) {
28 if (!va)
29 va = phys_to_virt(RNG_BASE, MEM_AREA_IO_SEC, RNG_SIZE);
30 return (vaddr_t)va;
31 }
32 return RNG_BASE;
33 }
34
hwrng_waithost_fifo_full(void)35 static inline int hwrng_waithost_fifo_full(void)
36 {
37 uint32_t status;
38
39 do {
40 status = io_read32(rng_base() + RNG_STATUS_OFFSET);
41 } while (!(status & RNG_STATUS_FULL));
42
43 if (status & (RNG_STATUS_ERR0 | RNG_STATUS_ERR1))
44 return 1;
45
46 return 0;
47 }
48
hw_get_random_byte(void)49 uint8_t hw_get_random_byte(void)
50 {
51 /*
52 * Only the HW RNG IP is used to generate the value through the
53 * HOST interface.
54 *
55 * @see the document rng_fspec_revG_120720.pdf for details
56 *
57 * - HOST FIFO size = 8x8b (64b)
58 * - LSB (16b) of the RNG_VAL register allows to read 16b
59 * - bit5 of the RNG_STATUS register allows to known if the HOST
60 * FIFO is full or not.
61 * - bit1,0 of the RNG_STATUS register allows to known if the
62 * data are valid.
63 *
64 * Main principle:
65 * For performance reason, a local SW fifo is used to store the
66 * content of the HOST FIFO (max size = 8bytes). When a random
67 * value is expected, this SW fifo is used to return a stored value.
68 * When the local SW fifo is empty, it is filled with the HOST FIFO
69 * according the following sequence:
70 *
71 * - wait HOST FIFO full
72 * o Indicates that max 8-bytes (64b) are available
73 * o This is mandatory to guarantee that a valid data is
74 * available. No STATUS bit to indicate that the HOST FIFO
75 * is empty is provided.
76 * - check STATUS bits
77 * - update the local SW fifo with the HOST FIFO
78 *
79 * This avoid to wait at each iteration that a valid random value is
80 * available. _LOCAL_FIFO_SIZE indicates the size of the local SW fifo.
81 *
82 */
83
84
85 #define _LOCAL_FIFO_SIZE 8 /* min 2, 4, 6, max 8 */
86
87 static uint8_t lfifo[_LOCAL_FIFO_SIZE]; /* local fifo */
88 static int pos = -1;
89
90 static int nbcall; /* debug purpose - 0 is the initial value*/
91
92 volatile uint32_t tmpval[_LOCAL_FIFO_SIZE/2];
93 uint8_t value;
94 int i;
95
96 nbcall++;
97
98 /* Retrieve data from local fifo */
99 if (pos >= 0) {
100 pos++;
101 value = lfifo[pos];
102 if (pos == (_LOCAL_FIFO_SIZE - 1))
103 pos = -1;
104 return value;
105 }
106
107 if (hwrng_waithost_fifo_full())
108 return 0;
109
110 /* Read the FIFO according the number of expected element */
111 for (i = 0; i < _LOCAL_FIFO_SIZE / 2; i++)
112 tmpval[i] = io_read32(rng_base() + RNG_VAL_OFFSET) & 0xFFFF;
113
114 /* Update the local SW fifo for next request */
115 pos = 0;
116 for (i = 0; i < _LOCAL_FIFO_SIZE / 2; i++) {
117 lfifo[pos] = tmpval[i] & 0xFF;
118 pos++;
119 lfifo[pos] = (tmpval[i] >> 8) & 0xFF;
120 pos++;
121 };
122
123 pos = 0;
124 return lfifo[pos];
125 }
126