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) < 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 
crypto_rng_read(void * buf,size_t len)169 TEE_Result crypto_rng_read(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 	assert(buf);
179 
180 	while (len) {
181 		status = io_read32(rngb.base.va + RNG_SR);
182 		if (status & RNG_SR_ERROR)
183 			return TEE_ERROR_BAD_STATE;
184 
185 		if (WORDS_IN_FIFO(status)) {
186 			val = io_read32(rngb.base.va + RNG_OUT);
187 			if (len > sizeof(uint32_t)) {
188 				len = len - sizeof(uint32_t);
189 				memcpy(rngbuf, &val, sizeof(uint32_t));
190 				rngbuf++;
191 			} else {
192 				memcpy(rngbuf, &val, len);
193 				len = 0;
194 			}
195 		}
196 	}
197 
198 	return TEE_SUCCESS;
199 }
200 
hw_get_random_byte(void)201 uint8_t hw_get_random_byte(void)
202 {
203 	uint8_t data = 0;
204 
205 	if (crypto_rng_read(&data, 1))
206 		panic();
207 
208 	return data;
209 }
210 
plat_rng_init(void)211 void plat_rng_init(void)
212 {
213 }
214 
rngb_init(void)215 static TEE_Result rngb_init(void)
216 {
217 	uint32_t type = 0;
218 
219 	if (map_controller())
220 		panic();
221 
222 	type = RNG_TYPE(io_read32(rngb.base.va + RNG_VER));
223 	if (type != RNG_TYPE_RNGB && type != RNG_TYPE_RNGC)
224 		panic();
225 
226 	rng_seed(&rngb);
227 	rngb.ready = true;
228 
229 	return TEE_SUCCESS;
230 }
231 
232 driver_init(rngb_init);
233