1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (c) 2022, Vaisala Oyj
4 */
5
6 #include <assert.h>
7 #include <io.h>
8 #include <kernel/boot.h>
9 #include <kernel/delay.h>
10 #include <kernel/dt.h>
11 #include <kernel/dt_driver.h>
12 #include <kernel/spinlock.h>
13 #include <libfdt.h>
14 #include <platform_config.h>
15 #include <rng_support.h>
16 #include <string.h>
17 #include <tee/tee_cryp_utl.h>
18
19 #define CONTROL_REG 0x00000000
20 #define STATUS_REG 0x00000004
21 #define RAND_REG 0x00000000
22
23 #define HOST_TO_TRNG_RESET 0x00000001
24 #define HOST_TO_TRNG_RELEASE_RESET 0x00000002
25 #define HOST_TO_TRNG_ENABLE 0x80000000
26 #define HOST_TO_TRNG_ZEROIZE 0x80000004
27 #define HOST_TO_TRNG_ACK_ZEROIZE 0x80000008
28 #define HOST_TO_TRNG_READ 0x8000000F
29
30 /* trng statuses */
31 #define TRNG_ACK_RESET 0x000000AC
32 #define TRNG_SUCCESSFUL_STARTUP 0x00000057
33 #define TRNG_FAILED_STARTUP 0x000000FA
34 #define TRNG_NEW_RAND_AVAILABLE 0x000000ED
35
36 static unsigned int trng_lock = SPINLOCK_UNLOCK;
37
38 static vaddr_t xiphera_trng_base;
39
xiphera_trng_random_available(void)40 static bool xiphera_trng_random_available(void)
41 {
42 uint32_t status = 0;
43
44 status = io_read32(xiphera_trng_base + STATUS_REG);
45
46 return status == TRNG_NEW_RAND_AVAILABLE;
47 }
48
xiphera_trng_read32(void)49 static uint32_t xiphera_trng_read32(void)
50 {
51 uint32_t value = 0;
52
53 value = io_read32(xiphera_trng_base + RAND_REG);
54
55 /*
56 * Ack that RNG value has been consumed and trigger new one to be
57 * generated
58 */
59 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_READ);
60 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE);
61
62 return value;
63 }
64
65 /* This is a true RNG, no need for seeding */
plat_rng_init(void)66 void plat_rng_init(void)
67 {
68 }
69
hw_get_random_bytes(void * buf,size_t len)70 TEE_Result hw_get_random_bytes(void *buf, size_t len)
71 {
72 uint8_t *rngbuf = buf;
73 uint32_t val = 0;
74 size_t len_to_copy = 0;
75
76 assert(buf);
77 assert(xiphera_trng_base);
78
79 while (len) {
80 uint32_t exceptions = cpu_spin_lock_xsave(&trng_lock);
81
82 if (xiphera_trng_random_available()) {
83 val = xiphera_trng_read32();
84
85 len_to_copy = MIN(len, sizeof(uint32_t));
86 memcpy(rngbuf, &val, len_to_copy);
87 rngbuf += len_to_copy;
88 len -= len_to_copy;
89 }
90
91 cpu_spin_unlock_xrestore(&trng_lock, exceptions);
92 }
93
94 return TEE_SUCCESS;
95 }
96
xiphera_trng_probe(const void * fdt,int node,const void * compat_data __unused)97 static TEE_Result xiphera_trng_probe(const void *fdt, int node,
98 const void *compat_data __unused)
99 {
100 int dt_status = _fdt_get_status(fdt, node);
101 uint32_t status = 0;
102 size_t size = 0;
103
104 /* Skip non-secure instances */
105 if (dt_status != DT_STATUS_OK_SEC)
106 return TEE_ERROR_NODE_DISABLED;
107
108 if (xiphera_trng_base) {
109 EMSG("Only one secure instance is supported");
110 return TEE_ERROR_GENERIC;
111 }
112
113 if (dt_map_dev(fdt, node, &xiphera_trng_base, &size, DT_MAP_AUTO) < 0)
114 return TEE_ERROR_GENERIC;
115
116 /*
117 * The TRNG needs to be first reset in order to provide stable
118 * operation.
119 *
120 * Reset of the chip should complete within 200 us but in some cases it
121 * could take up to 400 us. If it is not ready within 400 us assume
122 * there is problem.
123 */
124 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_RESET);
125 udelay(200);
126
127 status = io_read32(xiphera_trng_base + STATUS_REG);
128 if (status != TRNG_ACK_RESET) {
129 /*
130 * Give it additional 200 us to allow it to reset.
131 *
132 * If still not done -> error out.
133 */
134 udelay(200);
135 status = io_read32(xiphera_trng_base + STATUS_REG);
136 if (status != TRNG_ACK_RESET) {
137 EMSG("Failed to reset TRNG\n");
138 return TEE_ERROR_GENERIC;
139 }
140 }
141
142 /*
143 * Now TRNG should be internally stable.
144 *
145 * Clear internal random number generation engine to start in stable
146 * state and give it 20 ms to enable good random number entropy and
147 * then check that random number engine is ready.
148 */
149 io_write32(xiphera_trng_base + CONTROL_REG,
150 HOST_TO_TRNG_RELEASE_RESET);
151 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE);
152 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ZEROIZE);
153 mdelay(20);
154
155 status = io_read32(xiphera_trng_base + STATUS_REG);
156 if (status != TRNG_SUCCESSFUL_STARTUP) {
157 /*
158 * Check specifically if there were startup test errors to aid
159 * in debugging TRNG implementation in FPGA
160 */
161 if (status == TRNG_FAILED_STARTUP) {
162 EMSG("Startup tests have failed\n");
163 return TEE_ERROR_GENERIC;
164 }
165
166 EMSG("Startup tests yielded no response -> TRNG stuck\n");
167 return TEE_ERROR_GENERIC;
168 }
169
170 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE);
171
172 DMSG("TRNG initialized\n");
173
174 return TEE_SUCCESS;
175 }
176
177 static const struct dt_device_match xiphera_trng_match_table[] = {
178 { .compatible = "xiphera,xip8001b-trng" },
179 { }
180 };
181
182 DEFINE_DT_DRIVER(xiphera_trng_dt_driver) = {
183 .name = "xiphera_trng",
184 .type = DT_DRIVER_NOTYPE,
185 .match_table = xiphera_trng_match_table,
186 .probe = xiphera_trng_probe,
187 };
188