1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * (c) 2021 Jorge Ramirez <jorge@foundries.io>, Foundries Ltd.
4 */
5
6 #include <arm.h>
7 #include <crypto/crypto.h>
8 #include <initcall.h>
9 #include <io.h>
10 #include <kernel/boot.h>
11 #include <kernel/delay.h>
12 #include <kernel/dt.h>
13 #include <kernel/panic.h>
14 #include <libfdt.h>
15 #include <mm/core_memprot.h>
16 #include <mm/core_mmu.h>
17 #include <platform_config.h>
18 #include <rng_support.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <tee/tee_cryp_utl.h>
22 #include <trace.h>
23 #include <util.h>
24
25 #define RNG_VER 0x00
26 #define RNG_CMD 0x04
27 #define RNG_CR 0x08
28 #define RNG_SR 0x0C
29 #define RNG_ESR 0x10
30 #define RNG_OUT 0x14
31
32 #define RNG_CMD_CLR_INT BIT(4)
33 #define RNG_CMD_CLR_ERR BIT(5)
34
35 #define RNG_CR_AR BIT(4)
36 #define RNG_CR_MASK_DONE BIT(5)
37 #define RNG_CR_MASK_ERROR BIT(6)
38
39 #define RNG_SR_ST_DONE BIT(4)
40 #define RNG_SR_SEED_DONE BIT(5)
41 #define RNG_SR_ERROR BIT(16)
42 #define RNG_SR_FIFO_LEVEL_SHIFT 8
43 #define RNG_SR_FIFO_LEVEL_MASK GENMASK_32(11, RNG_SR_FIFO_LEVEL_SHIFT)
44
45 #define RNG_VER_TYPE_SHIFT 28
46 #define RNG_VER_TYPE_MASK GENMASK_32(31, RNG_VER_TYPE_SHIFT)
47
48 #define RNG_ESR_STATUS_STAT_ERR BIT(3)
49
50 #define RNG_TYPE_RNGA 0
51 #define RNG_TYPE_RNGB 1
52 #define RNG_TYPE_RNGC 2
53
54 #define SEED_TIMEOUT 2000000
55 #define IRQ_TIMEOUT 1000000
56
57 #define WORDS_IN_FIFO(__rng_sr) \
58 (((__rng_sr) & RNG_SR_FIFO_LEVEL_MASK) >> RNG_SR_FIFO_LEVEL_SHIFT)
59
60 #define RNG_TYPE(__rng_vr) \
61 (((__rng_vr) & RNG_VER_TYPE_MASK) >> RNG_VER_TYPE_SHIFT)
62
63 static struct imx_rng {
64 struct io_pa_va base;
65 size_t size;
66 bool ready;
67 uint32_t error;
68 } rngb = {
69 .base.pa = RNGB_BASE,
70 .size = 0x4000,
71 };
72
wait_for_irq(struct imx_rng * rng)73 static void wait_for_irq(struct imx_rng *rng)
74 {
75 uint64_t tref = timeout_init_us(IRQ_TIMEOUT);
76 uint32_t status = 0;
77
78 do {
79 rng->error = io_read32(rng->base.va + RNG_ESR);
80 status = io_read32(rng->base.va + RNG_SR);
81
82 if (timeout_elapsed(tref))
83 panic();
84
85 } while ((status & (RNG_SR_SEED_DONE | RNG_SR_ST_DONE)) == 0);
86 }
87
irq_clear(struct imx_rng * rng)88 static void irq_clear(struct imx_rng *rng)
89 {
90 io_setbits32(rng->base.va + RNG_CR,
91 RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR);
92 io_setbits32(rng->base.va + RNG_CMD,
93 RNG_CMD_CLR_INT | RNG_CMD_CLR_ERR);
94 }
95
irq_unmask(struct imx_rng * rng)96 static void irq_unmask(struct imx_rng *rng)
97 {
98 io_clrbits32(rng->base.va + RNG_CR,
99 RNG_CR_MASK_DONE | RNG_CR_MASK_ERROR);
100 }
101
rng_seed(struct imx_rng * rng)102 static void rng_seed(struct imx_rng *rng)
103 {
104 uint64_t tref = timeout_init_us(SEED_TIMEOUT);
105
106 irq_clear(rng);
107 do {
108 irq_unmask(rng);
109 /* configure continuous auto-reseed */
110 io_setbits32(rng->base.va + RNG_CR, RNG_CR_AR);
111 wait_for_irq(rng);
112 irq_clear(rng);
113
114 if (timeout_elapsed(tref))
115 panic();
116 } while (rng->error);
117 }
118
map_controller_static(void)119 static TEE_Result map_controller_static(void)
120 {
121 rngb.base.va = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC,
122 rngb.base.pa, rngb.size);
123 if (!rngb.base.va)
124 return TEE_ERROR_GENERIC;
125
126 return TEE_SUCCESS;
127 }
128
129 #if !defined(CFG_DT)
map_controller(void)130 static TEE_Result map_controller(void)
131 {
132 return map_controller_static();
133 }
134 #else
135 static const char *const rng_match_table[] = {
136 "fsl,imx25-rngb",
137 };
138
map_controller(void)139 static TEE_Result map_controller(void)
140 {
141 void *fdt = get_dt();
142 unsigned int i = 0;
143 int off = -1;
144
145 if (!fdt)
146 return map_controller_static();
147
148 for (i = 0; i < ARRAY_SIZE(rng_match_table); i++) {
149 off = fdt_node_offset_by_compatible(fdt, 0, rng_match_table[i]);
150 if (off >= 0)
151 break;
152 }
153
154 if (off < 0)
155 return map_controller_static();
156
157 if (dt_enable_secure_status(fdt, off))
158 return TEE_ERROR_NOT_SUPPORTED;
159
160 if (dt_map_dev(fdt, off, &rngb.base.va, &rngb.size, DT_MAP_AUTO) < 0)
161 return TEE_ERROR_NOT_SUPPORTED;
162
163 rngb.base.pa = virt_to_phys((void *)rngb.base.va);
164
165 return TEE_SUCCESS;
166 }
167 #endif
168
hw_get_random_bytes(void * buf,size_t len)169 TEE_Result hw_get_random_bytes(void *buf, size_t len)
170 {
171 uint32_t *rngbuf = buf;
172 uint32_t status = 0;
173 uint32_t val = 0;
174
175 if (!rngb.ready)
176 return TEE_ERROR_BAD_STATE;
177
178 while (len) {
179 status = io_read32(rngb.base.va + RNG_SR);
180 if (status & RNG_SR_ERROR)
181 return TEE_ERROR_BAD_STATE;
182
183 if (WORDS_IN_FIFO(status)) {
184 val = io_read32(rngb.base.va + RNG_OUT);
185 if (len > sizeof(uint32_t)) {
186 len = len - sizeof(uint32_t);
187 memcpy(rngbuf, &val, sizeof(uint32_t));
188 rngbuf++;
189 } else {
190 memcpy(rngbuf, &val, len);
191 len = 0;
192 }
193 }
194 }
195
196 return TEE_SUCCESS;
197 }
198
plat_rng_init(void)199 void plat_rng_init(void)
200 {
201 }
202
rngb_init(void)203 static TEE_Result rngb_init(void)
204 {
205 uint32_t type = 0;
206
207 if (map_controller())
208 panic();
209
210 type = RNG_TYPE(io_read32(rngb.base.va + RNG_VER));
211 if (type != RNG_TYPE_RNGB && type != RNG_TYPE_RNGC)
212 panic();
213
214 rng_seed(&rngb);
215 rngb.ready = true;
216
217 return TEE_SUCCESS;
218 }
219
220 driver_init(rngb_init);
221