xref: /optee_os/core/drivers/imx_rngb.c (revision c04a96a45ffe0e665a4d86e542ec921fae932aa8)
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 
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 
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 
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 
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 
119 static TEE_Result map_controller_static(void)
120 {
121 	if (!core_mmu_add_mapping(MEM_AREA_IO_SEC, rngb.base.pa, rngb.size))
122 		return TEE_ERROR_GENERIC;
123 
124 	rngb.base.va = (vaddr_t)phys_to_virt(rngb.base.pa, MEM_AREA_IO_SEC);
125 	if (rngb.base.va)
126 		return TEE_SUCCESS;
127 
128 	return TEE_ERROR_GENERIC;
129 }
130 
131 #if !defined(CFG_DT)
132 static TEE_Result map_controller(void)
133 {
134 	return map_controller_static();
135 }
136 #else
137 static const char *const rng_match_table[] =  {
138 	"fsl,imx25-rngb",
139 };
140 
141 static TEE_Result map_controller(void)
142 {
143 	void *fdt = get_dt();
144 	unsigned int i = 0;
145 	int off = -1;
146 
147 	if (!fdt)
148 		return map_controller_static();
149 
150 	for (i = 0; i < ARRAY_SIZE(rng_match_table); i++) {
151 		off = fdt_node_offset_by_compatible(fdt, 0, rng_match_table[i]);
152 		if (off >= 0)
153 			break;
154 	}
155 
156 	if (off < 0)
157 		return map_controller_static();
158 
159 	if (dt_enable_secure_status(fdt, off))
160 		return TEE_ERROR_NOT_SUPPORTED;
161 
162 	if (dt_map_dev(fdt, off, &rngb.base.va, &rngb.size) < 0)
163 		return TEE_ERROR_NOT_SUPPORTED;
164 
165 	rngb.base.pa = virt_to_phys((void *)rngb.base.va);
166 
167 	return TEE_SUCCESS;
168 }
169 #endif
170 
171 TEE_Result crypto_rng_read(void *buf, size_t len)
172 {
173 	uint32_t *rngbuf = buf;
174 	uint32_t status = 0;
175 	uint32_t val = 0;
176 
177 	if (!rngb.ready)
178 		return TEE_ERROR_BAD_STATE;
179 
180 	assert(buf);
181 
182 	while (len) {
183 		status = io_read32(rngb.base.va + RNG_SR);
184 		if (status & RNG_SR_ERROR)
185 			return TEE_ERROR_BAD_STATE;
186 
187 		if (WORDS_IN_FIFO(status)) {
188 			val = io_read32(rngb.base.va + RNG_OUT);
189 			if (len > sizeof(uint32_t)) {
190 				len = len - sizeof(uint32_t);
191 				memcpy(rngbuf, &val, sizeof(uint32_t));
192 				rngbuf++;
193 			} else {
194 				memcpy(rngbuf, &val, len);
195 				len = 0;
196 			}
197 		}
198 	}
199 
200 	return TEE_SUCCESS;
201 }
202 
203 uint8_t hw_get_random_byte(void)
204 {
205 	uint8_t data = 0;
206 
207 	if (crypto_rng_read(&data, 1))
208 		panic();
209 
210 	return data;
211 }
212 
213 void plat_rng_init(void)
214 {
215 }
216 
217 static TEE_Result rngb_init(void)
218 {
219 	uint32_t type = 0;
220 
221 	if (map_controller())
222 		panic();
223 
224 	type = RNG_TYPE(io_read32(rngb.base.va + RNG_VER));
225 	if (type != RNG_TYPE_RNGB && type != RNG_TYPE_RNGC)
226 		panic();
227 
228 	rng_seed(&rngb);
229 	rngb.ready = true;
230 
231 	return TEE_SUCCESS;
232 }
233 
234 driver_init(rngb_init);
235