xref: /rk3399_ARM-atf/drivers/st/crypto/stm32_rng.c (revision 864466beb0460537a648d11024e3db20c8901323)
1 /*
2  * Copyright (c) 2022-2025, STMicroelectronics - All Rights Reserved
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <stdbool.h>
10 
11 #include <arch_helpers.h>
12 #include <common/fdt_wrappers.h>
13 #include <drivers/clk.h>
14 #include <drivers/delay_timer.h>
15 #include <drivers/st/stm32_rng.h>
16 #include <drivers/st/stm32mp_reset.h>
17 #include <lib/mmio.h>
18 #include <libfdt.h>
19 
20 #include <platform_def.h>
21 
22 #if STM32_RNG_VER == 2
23 #define DT_RNG_COMPAT		"st,stm32-rng"
24 #endif
25 #if STM32_RNG_VER == 4
26 #define DT_RNG_COMPAT		"st,stm32mp13-rng"
27 #endif
28 #define RNG_CR			0x00U
29 #define RNG_SR			0x04U
30 #define RNG_DR			0x08U
31 
32 #define RNG_CR_RNGEN		BIT(2)
33 #define RNG_CR_IE		BIT(3)
34 #define RNG_CR_CED		BIT(5)
35 #define RNG_CR_CLKDIV		GENMASK(19, 16)
36 #define RNG_CR_CLKDIV_SHIFT	16U
37 #define RNG_CR_CONDRST		BIT(30)
38 
39 #define RNG_SR_DRDY		BIT(0)
40 #define RNG_SR_CECS		BIT(1)
41 #define RNG_SR_SECS		BIT(2)
42 #define RNG_SR_CEIS		BIT(5)
43 #define RNG_SR_SEIS		BIT(6)
44 
45 #define RNG_TIMEOUT_US		100000U
46 #define RNG_TIMEOUT_STEP_US	10U
47 
48 #define TIMEOUT_US_1MS		1000U
49 
50 #define RNG_NIST_CONFIG_A	0x00F40F00U
51 #define RNG_NIST_CONFIG_B	0x01801000U
52 #define RNG_NIST_CONFIG_C	0x00F00D00U
53 #define RNG_NIST_CONFIG_MASK	GENMASK(25, 8)
54 
55 #define RNG_MAX_NOISE_CLK_FREQ	48000000U
56 
57 struct stm32_rng_instance {
58 	uintptr_t base;
59 	unsigned long clock;
60 };
61 
62 static struct stm32_rng_instance stm32_rng;
63 
64 static void seed_error_recovery(void)
65 {
66 	uint8_t i __maybe_unused;
67 
68 	/* Recommended by the SoC reference manual */
69 	mmio_clrbits_32(stm32_rng.base + RNG_SR, RNG_SR_SEIS);
70 	dmbsy();
71 
72 #if STM32_RNG_VER == 2
73 	/* No Auto-reset on version 2, need to clean FIFO */
74 	for (i = 12U; i != 0U; i--) {
75 		(void)mmio_read_32(stm32_rng.base + RNG_DR);
76 	}
77 
78 	dmbsy();
79 #endif
80 
81 	if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_SEIS) != 0U) {
82 		ERROR("RNG noise\n");
83 		panic();
84 	}
85 }
86 
87 static uint32_t stm32_rng_clock_freq_restrain(void)
88 {
89 	unsigned long clock_rate;
90 	uint32_t clock_div = 0U;
91 
92 	clock_rate = clk_get_rate(stm32_rng.clock);
93 
94 	/*
95 	 * Get the exponent to apply on the CLKDIV field in RNG_CR register
96 	 * No need to handle the case when clock-div > 0xF as it is physically
97 	 * impossible
98 	 */
99 	while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ) {
100 		clock_div++;
101 	}
102 
103 	VERBOSE("RNG clk rate : %lu\n", clk_get_rate(stm32_rng.clock) >> clock_div);
104 
105 	return clock_div;
106 }
107 
108 static int stm32_rng_enable(void)
109 {
110 	uint32_t sr;
111 	uint64_t timeout;
112 	uint32_t clock_div __maybe_unused;
113 
114 #if STM32_RNG_VER == 2
115 	mmio_write_32(stm32_rng.base + RNG_CR, RNG_CR_RNGEN | RNG_CR_CED);
116 #endif
117 #if STM32_RNG_VER == 4
118 	/* Reset internal block and disable CED bit */
119 	clock_div = stm32_rng_clock_freq_restrain();
120 
121 	/* Update configuration fields */
122 	mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_NIST_CONFIG_MASK,
123 			   RNG_NIST_CONFIG_A | RNG_CR_CONDRST | RNG_CR_CED);
124 
125 	mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CLKDIV,
126 			   (clock_div << RNG_CR_CLKDIV_SHIFT));
127 
128 	mmio_clrsetbits_32(stm32_rng.base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN);
129 #endif
130 	timeout = timeout_init_us(RNG_TIMEOUT_US);
131 	sr = mmio_read_32(stm32_rng.base + RNG_SR);
132 	while ((sr & RNG_SR_DRDY) == 0U) {
133 		if (timeout_elapsed(timeout)) {
134 			WARN("Timeout waiting\n");
135 			return -ETIMEDOUT;
136 		}
137 
138 		if ((sr & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
139 			seed_error_recovery();
140 			timeout = timeout_init_us(RNG_TIMEOUT_US);
141 		}
142 
143 		udelay(RNG_TIMEOUT_STEP_US);
144 		sr = mmio_read_32(stm32_rng.base + RNG_SR);
145 	}
146 
147 	VERBOSE("Init RNG done\n");
148 
149 	return 0;
150 }
151 
152 static int check_data_validity(void)
153 {
154 	int nb_tries = RNG_TIMEOUT_US / RNG_TIMEOUT_STEP_US;
155 	uint32_t status = mmio_read_32(stm32_rng.base + RNG_SR);
156 
157 	/* Exit if data is ready without any seed error */
158 	if ((status & (RNG_SR_SECS | RNG_SR_SEIS | RNG_SR_DRDY)) != RNG_SR_DRDY) {
159 		do {
160 
161 			if ((status & (RNG_SR_SECS | RNG_SR_SEIS)) != 0U) {
162 				seed_error_recovery();
163 			}
164 
165 			udelay(RNG_TIMEOUT_STEP_US);
166 			nb_tries--;
167 			if (nb_tries == 0) {
168 				return -ETIMEDOUT;
169 			}
170 
171 			status = mmio_read_32(stm32_rng.base + RNG_SR);
172 		} while ((status & RNG_SR_DRDY) == 0U);
173 	}
174 
175 	return 0;
176 }
177 
178 /*
179  * stm32_rng_read - Read a number of random bytes from RNG
180  * out: pointer to the output buffer
181  * size: number of bytes to be read
182  * Return 0 on success, non-0 on failure
183  */
184 int stm32_rng_read(uint8_t *out, uint32_t size)
185 {
186 	uint8_t *buf = out;
187 	size_t len = size;
188 	uint32_t data32;
189 	int rc = 0;
190 	unsigned int count;
191 
192 	if (stm32_rng.base == 0U) {
193 		return -EPERM;
194 	}
195 
196 	while (len != 0U) {
197 		rc = check_data_validity();
198 		if (rc != 0) {
199 			goto bail;
200 		}
201 
202 		count = 4U;
203 		while (len != 0U) {
204 			if ((mmio_read_32(stm32_rng.base + RNG_SR) & RNG_SR_DRDY) == 0U) {
205 				break;
206 			}
207 
208 			data32 = mmio_read_32(stm32_rng.base + RNG_DR);
209 
210 			while (data32 == 0U) {
211 				rc = check_data_validity();
212 				if (rc != 0) {
213 					goto bail;
214 				}
215 
216 				data32 = mmio_read_32(stm32_rng.base + RNG_DR);
217 			}
218 
219 			count--;
220 
221 			(void)memcpy(buf, (uint8_t *)&data32, MIN(len, sizeof(uint32_t)));
222 			buf += MIN(len, sizeof(uint32_t));
223 			len -= MIN(len, sizeof(uint32_t));
224 
225 			if (count == 0U) {
226 				break;
227 			}
228 		}
229 	}
230 
231 bail:
232 	if (rc != 0) {
233 		(void)memset(out, 0, buf - out);
234 	}
235 
236 	return rc;
237 }
238 
239 /*
240  * stm32_rng_select: Select a specified RNG instance from its base address.
241  * This function only works if the driver is uninitialized.
242  */
243 void stm32_rng_select(uintptr_t rng_base)
244 {
245 	if ((stm32_rng.base == 0U) || (stm32_rng.clock == 0U)) {
246 		/* RNG instance is selected once */
247 		stm32_rng.base = rng_base;
248 	}
249 }
250 
251 /*
252  * stm32_rng_init: Initialize rng from DT
253  * return 0 on success, negative value on failure
254  */
255 int stm32_rng_init(void)
256 {
257 	struct stm32_rng_instance rng = {0, 0};
258 	void *fdt;
259 	int node;
260 	int success = 0;
261 	int disabled = 0;
262 
263 	if (stm32_rng.base != 0U) {
264 		if (stm32_rng.clock != 0U) {
265 			/* Driver is already initialized */
266 			return 0;
267 		}
268 
269 		rng.base = stm32_rng.base;
270 	}
271 
272 	if (fdt_get_address(&fdt) == 0) {
273 		panic();
274 	}
275 
276 	fdt_for_each_compatible_node(fdt, node, DT_RNG_COMPAT) {
277 		struct dt_node_info dt_rng;
278 		int ret;
279 
280 		dt_fill_device_info(&dt_rng, node);
281 
282 		VERBOSE("Setting up rng@%x, status: %x\n", dt_rng.base, dt_rng.status);
283 
284 		/*
285 		 * All the valid RNG peripherals available in device tree are
286 		 * activated but only the last RNG found is assigned to the RNG
287 		 * instance of the driver.
288 		 */
289 		if ((dt_rng.status == DT_DISABLED) || (dt_rng.base == 0U)) {
290 			disabled++;
291 			continue;
292 		}
293 
294 		stm32_rng.base = dt_rng.base;
295 
296 		if (dt_rng.clock < 0) {
297 			panic();
298 		}
299 
300 		stm32_rng.clock = (unsigned long)dt_rng.clock;
301 		clk_enable(stm32_rng.clock);
302 
303 		if (stm32_rng.base == rng.base) {
304 			/* Set the rng instance as the rng to use by TF-A */
305 			rng.clock = stm32_rng.clock;
306 		}
307 
308 		if (dt_rng.reset >= 0) {
309 
310 			ret = stm32mp_reset_assert((unsigned long)dt_rng.reset, TIMEOUT_US_1MS);
311 			if (ret != 0) {
312 				panic();
313 			}
314 
315 			udelay(20);
316 
317 			ret = stm32mp_reset_deassert((unsigned long)dt_rng.reset, TIMEOUT_US_1MS);
318 			if (ret != 0) {
319 				panic();
320 			}
321 		}
322 
323 		ret = stm32_rng_enable();
324 		if (ret != 0) {
325 			ERROR("Failed to enable rng@%x\n", dt_rng.base);
326 		} else {
327 			success++;
328 		}
329 	}
330 
331 	if ((success == 0) && (disabled > 0)) {
332 		WARN("%s: No RNG found in device tree.\n", __func__);
333 		return 0;
334 	} else if (success > 0) {
335 		if ((rng.clock != 0U) && (rng.base != 0U)) {
336 			stm32_rng = rng;
337 		}
338 		return 0;
339 	} else {
340 		return -ENODEV;
341 	}
342 }
343