1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (c) 2015, Daniel Thompson |
4 | */ |
5 | |
6 | #include <linux/clk.h> |
7 | #include <linux/delay.h> |
8 | #include <linux/hw_random.h> |
9 | #include <linux/io.h> |
10 | #include <linux/iopoll.h> |
11 | #include <linux/kernel.h> |
12 | #include <linux/module.h> |
13 | #include <linux/of.h> |
14 | #include <linux/of_address.h> |
15 | #include <linux/platform_device.h> |
16 | #include <linux/pm_runtime.h> |
17 | #include <linux/reset.h> |
18 | #include <linux/slab.h> |
19 | |
20 | #define RNG_CR 0x00 |
21 | #define RNG_CR_RNGEN BIT(2) |
22 | #define RNG_CR_CED BIT(5) |
23 | #define RNG_CR_CONFIG1 GENMASK(11, 8) |
24 | #define RNG_CR_NISTC BIT(12) |
25 | #define RNG_CR_CONFIG2 GENMASK(15, 13) |
26 | #define RNG_CR_CLKDIV_SHIFT 16 |
27 | #define RNG_CR_CLKDIV GENMASK(19, 16) |
28 | #define RNG_CR_CONFIG3 GENMASK(25, 20) |
29 | #define RNG_CR_CONDRST BIT(30) |
30 | #define RNG_CR_CONFLOCK BIT(31) |
31 | #define RNG_CR_ENTROPY_SRC_MASK (RNG_CR_CONFIG1 | RNG_CR_NISTC | RNG_CR_CONFIG2 | RNG_CR_CONFIG3) |
32 | #define RNG_CR_CONFIG_MASK (RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED | RNG_CR_CLKDIV) |
33 | |
34 | #define RNG_SR 0x04 |
35 | #define RNG_SR_DRDY BIT(0) |
36 | #define RNG_SR_CECS BIT(1) |
37 | #define RNG_SR_SECS BIT(2) |
38 | #define RNG_SR_CEIS BIT(5) |
39 | #define RNG_SR_SEIS BIT(6) |
40 | |
41 | #define RNG_DR 0x08 |
42 | |
43 | #define RNG_NSCR 0x0C |
44 | #define RNG_NSCR_MASK GENMASK(17, 0) |
45 | |
46 | #define RNG_HTCR 0x10 |
47 | |
48 | #define RNG_NB_RECOVER_TRIES 3 |
49 | |
50 | struct stm32_rng_data { |
51 | uint max_clock_rate; |
52 | u32 cr; |
53 | u32 nscr; |
54 | u32 htcr; |
55 | bool has_cond_reset; |
56 | }; |
57 | |
58 | /** |
59 | * struct stm32_rng_config - RNG configuration data |
60 | * |
61 | * @cr: RNG configuration. 0 means default hardware RNG configuration |
62 | * @nscr: Noise sources control configuration. |
63 | * @htcr: Health tests configuration. |
64 | */ |
65 | struct stm32_rng_config { |
66 | u32 cr; |
67 | u32 nscr; |
68 | u32 htcr; |
69 | }; |
70 | |
71 | struct stm32_rng_private { |
72 | struct hwrng rng; |
73 | void __iomem *base; |
74 | struct clk *clk; |
75 | struct reset_control *rst; |
76 | struct stm32_rng_config pm_conf; |
77 | const struct stm32_rng_data *data; |
78 | bool ced; |
79 | bool lock_conf; |
80 | }; |
81 | |
82 | /* |
83 | * Extracts from the STM32 RNG specification when RNG supports CONDRST. |
84 | * |
85 | * When a noise source (or seed) error occurs, the RNG stops generating |
86 | * random numbers and sets to “1” both SEIS and SECS bits to indicate |
87 | * that a seed error occurred. (...) |
88 | * |
89 | * 1. Software reset by writing CONDRST at 1 and at 0 (see bitfield |
90 | * description for details). This step is needed only if SECS is set. |
91 | * Indeed, when SEIS is set and SECS is cleared it means RNG performed |
92 | * the reset automatically (auto-reset). |
93 | * 2. If SECS was set in step 1 (no auto-reset) wait for CONDRST |
94 | * to be cleared in the RNG_CR register, then confirm that SEIS is |
95 | * cleared in the RNG_SR register. Otherwise just clear SEIS bit in |
96 | * the RNG_SR register. |
97 | * 3. If SECS was set in step 1 (no auto-reset) wait for SECS to be |
98 | * cleared by RNG. The random number generation is now back to normal. |
99 | */ |
100 | static int stm32_rng_conceal_seed_error_cond_reset(struct stm32_rng_private *priv) |
101 | { |
102 | struct device *dev = (struct device *)priv->rng.priv; |
103 | u32 sr = readl_relaxed(priv->base + RNG_SR); |
104 | u32 cr = readl_relaxed(priv->base + RNG_CR); |
105 | int err; |
106 | |
107 | if (sr & RNG_SR_SECS) { |
108 | /* Conceal by resetting the subsystem (step 1.) */ |
109 | writel_relaxed(cr | RNG_CR_CONDRST, priv->base + RNG_CR); |
110 | writel_relaxed(cr & ~RNG_CR_CONDRST, priv->base + RNG_CR); |
111 | } else { |
112 | /* RNG auto-reset (step 2.) */ |
113 | writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR); |
114 | goto end; |
115 | } |
116 | |
117 | err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, cr, !(cr & RNG_CR_CONDRST), 10, |
118 | 100000); |
119 | if (err) { |
120 | dev_err(dev, "%s: timeout %x\n" , __func__, sr); |
121 | return err; |
122 | } |
123 | |
124 | /* Check SEIS is cleared (step 2.) */ |
125 | if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS) |
126 | return -EINVAL; |
127 | |
128 | err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, sr, !(sr & RNG_SR_SECS), 10, |
129 | 100000); |
130 | if (err) { |
131 | dev_err(dev, "%s: timeout %x\n" , __func__, sr); |
132 | return err; |
133 | } |
134 | |
135 | end: |
136 | return 0; |
137 | } |
138 | |
139 | /* |
140 | * Extracts from the STM32 RNG specification, when CONDRST is not supported |
141 | * |
142 | * When a noise source (or seed) error occurs, the RNG stops generating |
143 | * random numbers and sets to “1” both SEIS and SECS bits to indicate |
144 | * that a seed error occurred. (...) |
145 | * |
146 | * The following sequence shall be used to fully recover from a seed |
147 | * error after the RNG initialization: |
148 | * 1. Clear the SEIS bit by writing it to “0”. |
149 | * 2. Read out 12 words from the RNG_DR register, and discard each of |
150 | * them in order to clean the pipeline. |
151 | * 3. Confirm that SEIS is still cleared. Random number generation is |
152 | * back to normal. |
153 | */ |
154 | static int stm32_rng_conceal_seed_error_sw_reset(struct stm32_rng_private *priv) |
155 | { |
156 | unsigned int i = 0; |
157 | u32 sr = readl_relaxed(priv->base + RNG_SR); |
158 | |
159 | writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR); |
160 | |
161 | for (i = 12; i != 0; i--) |
162 | (void)readl_relaxed(priv->base + RNG_DR); |
163 | |
164 | if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS) |
165 | return -EINVAL; |
166 | |
167 | return 0; |
168 | } |
169 | |
170 | static int stm32_rng_conceal_seed_error(struct hwrng *rng) |
171 | { |
172 | struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); |
173 | |
174 | dev_dbg((struct device *)priv->rng.priv, "Concealing seed error\n" ); |
175 | |
176 | if (priv->data->has_cond_reset) |
177 | return stm32_rng_conceal_seed_error_cond_reset(priv); |
178 | else |
179 | return stm32_rng_conceal_seed_error_sw_reset(priv); |
180 | }; |
181 | |
182 | |
183 | static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) |
184 | { |
185 | struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); |
186 | unsigned int i = 0; |
187 | int retval = 0, err = 0; |
188 | u32 sr; |
189 | |
190 | pm_runtime_get_sync(dev: (struct device *) priv->rng.priv); |
191 | |
192 | if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS) |
193 | stm32_rng_conceal_seed_error(rng); |
194 | |
195 | while (max >= sizeof(u32)) { |
196 | sr = readl_relaxed(priv->base + RNG_SR); |
197 | /* |
198 | * Manage timeout which is based on timer and take |
199 | * care of initial delay time when enabling the RNG. |
200 | */ |
201 | if (!sr && wait) { |
202 | err = readl_relaxed_poll_timeout_atomic(priv->base |
203 | + RNG_SR, |
204 | sr, sr, |
205 | 10, 50000); |
206 | if (err) { |
207 | dev_err((struct device *)priv->rng.priv, |
208 | "%s: timeout %x!\n" , __func__, sr); |
209 | break; |
210 | } |
211 | } else if (!sr) { |
212 | /* The FIFO is being filled up */ |
213 | break; |
214 | } |
215 | |
216 | if (sr != RNG_SR_DRDY) { |
217 | if (sr & RNG_SR_SEIS) { |
218 | err = stm32_rng_conceal_seed_error(rng); |
219 | i++; |
220 | if (err && i > RNG_NB_RECOVER_TRIES) { |
221 | dev_err((struct device *)priv->rng.priv, |
222 | "Couldn't recover from seed error\n" ); |
223 | return -ENOTRECOVERABLE; |
224 | } |
225 | |
226 | continue; |
227 | } |
228 | |
229 | if (WARN_ONCE((sr & RNG_SR_CEIS), "RNG clock too slow - %x\n" , sr)) |
230 | writel_relaxed(0, priv->base + RNG_SR); |
231 | } |
232 | |
233 | /* Late seed error case: DR being 0 is an error status */ |
234 | *(u32 *)data = readl_relaxed(priv->base + RNG_DR); |
235 | if (!*(u32 *)data) { |
236 | err = stm32_rng_conceal_seed_error(rng); |
237 | i++; |
238 | if (err && i > RNG_NB_RECOVER_TRIES) { |
239 | dev_err((struct device *)priv->rng.priv, |
240 | "Couldn't recover from seed error" ); |
241 | return -ENOTRECOVERABLE; |
242 | } |
243 | |
244 | continue; |
245 | } |
246 | |
247 | i = 0; |
248 | retval += sizeof(u32); |
249 | data += sizeof(u32); |
250 | max -= sizeof(u32); |
251 | } |
252 | |
253 | pm_runtime_mark_last_busy(dev: (struct device *) priv->rng.priv); |
254 | pm_runtime_put_sync_autosuspend(dev: (struct device *) priv->rng.priv); |
255 | |
256 | return retval || !wait ? retval : -EIO; |
257 | } |
258 | |
259 | static uint stm32_rng_clock_freq_restrain(struct hwrng *rng) |
260 | { |
261 | struct stm32_rng_private *priv = |
262 | container_of(rng, struct stm32_rng_private, rng); |
263 | unsigned long clock_rate = 0; |
264 | uint clock_div = 0; |
265 | |
266 | clock_rate = clk_get_rate(clk: priv->clk); |
267 | |
268 | /* |
269 | * Get the exponent to apply on the CLKDIV field in RNG_CR register |
270 | * No need to handle the case when clock-div > 0xF as it is physically |
271 | * impossible |
272 | */ |
273 | while ((clock_rate >> clock_div) > priv->data->max_clock_rate) |
274 | clock_div++; |
275 | |
276 | pr_debug("RNG clk rate : %lu\n" , clk_get_rate(priv->clk) >> clock_div); |
277 | |
278 | return clock_div; |
279 | } |
280 | |
281 | static int stm32_rng_init(struct hwrng *rng) |
282 | { |
283 | struct stm32_rng_private *priv = |
284 | container_of(rng, struct stm32_rng_private, rng); |
285 | int err; |
286 | u32 reg; |
287 | |
288 | err = clk_prepare_enable(clk: priv->clk); |
289 | if (err) |
290 | return err; |
291 | |
292 | /* clear error indicators */ |
293 | writel_relaxed(0, priv->base + RNG_SR); |
294 | |
295 | reg = readl_relaxed(priv->base + RNG_CR); |
296 | |
297 | /* |
298 | * Keep default RNG configuration if none was specified. |
299 | * 0 is an invalid value as it disables all entropy sources. |
300 | */ |
301 | if (priv->data->has_cond_reset && priv->data->cr) { |
302 | uint clock_div = stm32_rng_clock_freq_restrain(rng); |
303 | |
304 | reg &= ~RNG_CR_CONFIG_MASK; |
305 | reg |= RNG_CR_CONDRST | (priv->data->cr & RNG_CR_ENTROPY_SRC_MASK) | |
306 | (clock_div << RNG_CR_CLKDIV_SHIFT); |
307 | if (priv->ced) |
308 | reg &= ~RNG_CR_CED; |
309 | else |
310 | reg |= RNG_CR_CED; |
311 | writel_relaxed(reg, priv->base + RNG_CR); |
312 | |
313 | /* Health tests and noise control registers */ |
314 | writel_relaxed(priv->data->htcr, priv->base + RNG_HTCR); |
315 | writel_relaxed(priv->data->nscr & RNG_NSCR_MASK, priv->base + RNG_NSCR); |
316 | |
317 | reg &= ~RNG_CR_CONDRST; |
318 | reg |= RNG_CR_RNGEN; |
319 | if (priv->lock_conf) |
320 | reg |= RNG_CR_CONFLOCK; |
321 | |
322 | writel_relaxed(reg, priv->base + RNG_CR); |
323 | |
324 | err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg, |
325 | (!(reg & RNG_CR_CONDRST)), |
326 | 10, 50000); |
327 | if (err) { |
328 | dev_err((struct device *)priv->rng.priv, |
329 | "%s: timeout %x!\n" , __func__, reg); |
330 | return -EINVAL; |
331 | } |
332 | } else { |
333 | /* Handle all RNG versions by checking if conditional reset should be set */ |
334 | if (priv->data->has_cond_reset) |
335 | reg |= RNG_CR_CONDRST; |
336 | |
337 | if (priv->ced) |
338 | reg &= ~RNG_CR_CED; |
339 | else |
340 | reg |= RNG_CR_CED; |
341 | |
342 | writel_relaxed(reg, priv->base + RNG_CR); |
343 | |
344 | if (priv->data->has_cond_reset) |
345 | reg &= ~RNG_CR_CONDRST; |
346 | |
347 | reg |= RNG_CR_RNGEN; |
348 | |
349 | writel_relaxed(reg, priv->base + RNG_CR); |
350 | } |
351 | |
352 | err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, reg, |
353 | reg & RNG_SR_DRDY, |
354 | 10, 100000); |
355 | if (err | (reg & ~RNG_SR_DRDY)) { |
356 | clk_disable_unprepare(clk: priv->clk); |
357 | dev_err((struct device *)priv->rng.priv, |
358 | "%s: timeout:%x SR: %x!\n" , __func__, err, reg); |
359 | return -EINVAL; |
360 | } |
361 | |
362 | return 0; |
363 | } |
364 | |
365 | static int stm32_rng_remove(struct platform_device *ofdev) |
366 | { |
367 | pm_runtime_disable(dev: &ofdev->dev); |
368 | |
369 | return 0; |
370 | } |
371 | |
372 | static int __maybe_unused stm32_rng_runtime_suspend(struct device *dev) |
373 | { |
374 | struct stm32_rng_private *priv = dev_get_drvdata(dev); |
375 | u32 reg; |
376 | |
377 | reg = readl_relaxed(priv->base + RNG_CR); |
378 | reg &= ~RNG_CR_RNGEN; |
379 | writel_relaxed(reg, priv->base + RNG_CR); |
380 | clk_disable_unprepare(clk: priv->clk); |
381 | |
382 | return 0; |
383 | } |
384 | |
385 | static int __maybe_unused stm32_rng_suspend(struct device *dev) |
386 | { |
387 | struct stm32_rng_private *priv = dev_get_drvdata(dev); |
388 | |
389 | if (priv->data->has_cond_reset) { |
390 | priv->pm_conf.nscr = readl_relaxed(priv->base + RNG_NSCR); |
391 | priv->pm_conf.htcr = readl_relaxed(priv->base + RNG_HTCR); |
392 | } |
393 | |
394 | /* Do not save that RNG is enabled as it will be handled at resume */ |
395 | priv->pm_conf.cr = readl_relaxed(priv->base + RNG_CR) & ~RNG_CR_RNGEN; |
396 | |
397 | writel_relaxed(priv->pm_conf.cr, priv->base + RNG_CR); |
398 | |
399 | clk_disable_unprepare(clk: priv->clk); |
400 | |
401 | return 0; |
402 | } |
403 | |
404 | static int __maybe_unused stm32_rng_runtime_resume(struct device *dev) |
405 | { |
406 | struct stm32_rng_private *priv = dev_get_drvdata(dev); |
407 | int err; |
408 | u32 reg; |
409 | |
410 | err = clk_prepare_enable(clk: priv->clk); |
411 | if (err) |
412 | return err; |
413 | |
414 | /* Clean error indications */ |
415 | writel_relaxed(0, priv->base + RNG_SR); |
416 | |
417 | reg = readl_relaxed(priv->base + RNG_CR); |
418 | reg |= RNG_CR_RNGEN; |
419 | writel_relaxed(reg, priv->base + RNG_CR); |
420 | |
421 | return 0; |
422 | } |
423 | |
424 | static int __maybe_unused stm32_rng_resume(struct device *dev) |
425 | { |
426 | struct stm32_rng_private *priv = dev_get_drvdata(dev); |
427 | int err; |
428 | u32 reg; |
429 | |
430 | err = clk_prepare_enable(clk: priv->clk); |
431 | if (err) |
432 | return err; |
433 | |
434 | /* Clean error indications */ |
435 | writel_relaxed(0, priv->base + RNG_SR); |
436 | |
437 | if (priv->data->has_cond_reset) { |
438 | /* |
439 | * Correct configuration in bits [29:4] must be set in the same |
440 | * access that set RNG_CR_CONDRST bit. Else config setting is |
441 | * not taken into account. CONFIGLOCK bit must also be unset but |
442 | * it is not handled at the moment. |
443 | */ |
444 | writel_relaxed(priv->pm_conf.cr | RNG_CR_CONDRST, priv->base + RNG_CR); |
445 | |
446 | writel_relaxed(priv->pm_conf.nscr, priv->base + RNG_NSCR); |
447 | writel_relaxed(priv->pm_conf.htcr, priv->base + RNG_HTCR); |
448 | |
449 | reg = readl_relaxed(priv->base + RNG_CR); |
450 | reg |= RNG_CR_RNGEN; |
451 | reg &= ~RNG_CR_CONDRST; |
452 | writel_relaxed(reg, priv->base + RNG_CR); |
453 | |
454 | err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg, |
455 | reg & ~RNG_CR_CONDRST, 10, 100000); |
456 | |
457 | if (err) { |
458 | clk_disable_unprepare(clk: priv->clk); |
459 | dev_err((struct device *)priv->rng.priv, |
460 | "%s: timeout:%x CR: %x!\n" , __func__, err, reg); |
461 | return -EINVAL; |
462 | } |
463 | } else { |
464 | reg = priv->pm_conf.cr; |
465 | reg |= RNG_CR_RNGEN; |
466 | writel_relaxed(reg, priv->base + RNG_CR); |
467 | } |
468 | |
469 | return 0; |
470 | } |
471 | |
472 | static const struct dev_pm_ops __maybe_unused stm32_rng_pm_ops = { |
473 | SET_RUNTIME_PM_OPS(stm32_rng_runtime_suspend, |
474 | stm32_rng_runtime_resume, NULL) |
475 | SET_SYSTEM_SLEEP_PM_OPS(stm32_rng_suspend, |
476 | stm32_rng_resume) |
477 | }; |
478 | |
479 | static const struct stm32_rng_data stm32mp13_rng_data = { |
480 | .has_cond_reset = true, |
481 | .max_clock_rate = 48000000, |
482 | .cr = 0x00F00D00, |
483 | .nscr = 0x2B5BB, |
484 | .htcr = 0x969D, |
485 | }; |
486 | |
487 | static const struct stm32_rng_data stm32_rng_data = { |
488 | .has_cond_reset = false, |
489 | .max_clock_rate = 3000000, |
490 | }; |
491 | |
492 | static const struct of_device_id stm32_rng_match[] = { |
493 | { |
494 | .compatible = "st,stm32mp13-rng" , |
495 | .data = &stm32mp13_rng_data, |
496 | }, |
497 | { |
498 | .compatible = "st,stm32-rng" , |
499 | .data = &stm32_rng_data, |
500 | }, |
501 | {}, |
502 | }; |
503 | MODULE_DEVICE_TABLE(of, stm32_rng_match); |
504 | |
505 | static int stm32_rng_probe(struct platform_device *ofdev) |
506 | { |
507 | struct device *dev = &ofdev->dev; |
508 | struct device_node *np = ofdev->dev.of_node; |
509 | struct stm32_rng_private *priv; |
510 | struct resource *res; |
511 | |
512 | priv = devm_kzalloc(dev, size: sizeof(struct stm32_rng_private), GFP_KERNEL); |
513 | if (!priv) |
514 | return -ENOMEM; |
515 | |
516 | priv->base = devm_platform_get_and_ioremap_resource(pdev: ofdev, index: 0, res: &res); |
517 | if (IS_ERR(ptr: priv->base)) |
518 | return PTR_ERR(ptr: priv->base); |
519 | |
520 | priv->clk = devm_clk_get(dev: &ofdev->dev, NULL); |
521 | if (IS_ERR(ptr: priv->clk)) |
522 | return PTR_ERR(ptr: priv->clk); |
523 | |
524 | priv->rst = devm_reset_control_get(dev: &ofdev->dev, NULL); |
525 | if (!IS_ERR(ptr: priv->rst)) { |
526 | reset_control_assert(rstc: priv->rst); |
527 | udelay(2); |
528 | reset_control_deassert(rstc: priv->rst); |
529 | } |
530 | |
531 | priv->ced = of_property_read_bool(np, propname: "clock-error-detect" ); |
532 | priv->lock_conf = of_property_read_bool(np, propname: "st,rng-lock-conf" ); |
533 | |
534 | priv->data = of_device_get_match_data(dev); |
535 | if (!priv->data) |
536 | return -ENODEV; |
537 | |
538 | dev_set_drvdata(dev, data: priv); |
539 | |
540 | priv->rng.name = dev_driver_string(dev); |
541 | priv->rng.init = stm32_rng_init; |
542 | priv->rng.read = stm32_rng_read; |
543 | priv->rng.priv = (unsigned long) dev; |
544 | priv->rng.quality = 900; |
545 | |
546 | pm_runtime_set_autosuspend_delay(dev, delay: 100); |
547 | pm_runtime_use_autosuspend(dev); |
548 | pm_runtime_enable(dev); |
549 | |
550 | return devm_hwrng_register(dev, rng: &priv->rng); |
551 | } |
552 | |
553 | static struct platform_driver stm32_rng_driver = { |
554 | .driver = { |
555 | .name = "stm32-rng" , |
556 | .pm = pm_ptr(&stm32_rng_pm_ops), |
557 | .of_match_table = stm32_rng_match, |
558 | }, |
559 | .probe = stm32_rng_probe, |
560 | .remove = stm32_rng_remove, |
561 | }; |
562 | |
563 | module_platform_driver(stm32_rng_driver); |
564 | |
565 | MODULE_LICENSE("GPL" ); |
566 | MODULE_AUTHOR("Daniel Thompson <daniel.thompson@linaro.org>" ); |
567 | MODULE_DESCRIPTION("STMicroelectronics STM32 RNG device driver" ); |
568 | |