Lines Matching +full:rng +full:- +full:lock +full:- +full:conf
1 // SPDX-License-Identifier: GPL-2.0-or-later
7 #include <linux/clk-provider.h>
61 * struct stm32_rng_config - RNG configuration data
63 * @cr: RNG configuration. 0 means default hardware RNG configuration
74 struct hwrng rng; member
86 * Extracts from the STM32 RNG specification when RNG supports CONDRST.
88 * When a noise source (or seed) error occurs, the RNG stops generating
94 * Indeed, when SEIS is set and SECS is cleared it means RNG performed
95 * the reset automatically (auto-reset).
96 * 2. If SECS was set in step 1 (no auto-reset) wait for CONDRST
100 * 3. If SECS was set in step 1 (no auto-reset) wait for SECS to be
101 * cleared by RNG. The random number generation is now back to normal.
105 struct device *dev = priv->dev; in stm32_rng_conceal_seed_error_cond_reset()
106 u32 sr = readl_relaxed(priv->base + RNG_SR); in stm32_rng_conceal_seed_error_cond_reset()
107 u32 cr = readl_relaxed(priv->base + RNG_CR); in stm32_rng_conceal_seed_error_cond_reset()
112 writel_relaxed(cr | RNG_CR_CONDRST, priv->base + RNG_CR); in stm32_rng_conceal_seed_error_cond_reset()
113 writel_relaxed(cr & ~RNG_CR_CONDRST, priv->base + RNG_CR); in stm32_rng_conceal_seed_error_cond_reset()
115 /* RNG auto-reset (step 2.) */ in stm32_rng_conceal_seed_error_cond_reset()
116 writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR); in stm32_rng_conceal_seed_error_cond_reset()
120 err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, cr, !(cr & RNG_CR_CONDRST), 10, in stm32_rng_conceal_seed_error_cond_reset()
128 if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS) in stm32_rng_conceal_seed_error_cond_reset()
129 return -EINVAL; in stm32_rng_conceal_seed_error_cond_reset()
131 err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, sr, !(sr & RNG_SR_SECS), 10, in stm32_rng_conceal_seed_error_cond_reset()
143 * Extracts from the STM32 RNG specification, when CONDRST is not supported
145 * When a noise source (or seed) error occurs, the RNG stops generating
150 * error after the RNG initialization:
160 u32 sr = readl_relaxed(priv->base + RNG_SR); in stm32_rng_conceal_seed_error_sw_reset()
162 writel_relaxed(sr & ~RNG_SR_SEIS, priv->base + RNG_SR); in stm32_rng_conceal_seed_error_sw_reset()
164 for (i = 12; i != 0; i--) in stm32_rng_conceal_seed_error_sw_reset()
165 (void)readl_relaxed(priv->base + RNG_DR); in stm32_rng_conceal_seed_error_sw_reset()
167 if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS) in stm32_rng_conceal_seed_error_sw_reset()
168 return -EINVAL; in stm32_rng_conceal_seed_error_sw_reset()
173 static int stm32_rng_conceal_seed_error(struct hwrng *rng) in stm32_rng_conceal_seed_error() argument
175 struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); in stm32_rng_conceal_seed_error()
177 dev_dbg(priv->dev, "Concealing seed error\n"); in stm32_rng_conceal_seed_error()
179 if (priv->data->has_cond_reset) in stm32_rng_conceal_seed_error()
186 static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) in stm32_rng_read() argument
188 struct stm32_rng_private *priv = container_of(rng, struct stm32_rng_private, rng); in stm32_rng_read()
193 retval = pm_runtime_resume_and_get(priv->dev); in stm32_rng_read()
197 if (readl_relaxed(priv->base + RNG_SR) & RNG_SR_SEIS) in stm32_rng_read()
198 stm32_rng_conceal_seed_error(rng); in stm32_rng_read()
201 sr = readl_relaxed(priv->base + RNG_SR); in stm32_rng_read()
204 * care of initial delay time when enabling the RNG. in stm32_rng_read()
207 err = readl_relaxed_poll_timeout_atomic(priv->base in stm32_rng_read()
212 dev_err(priv->dev, "%s: timeout %x!\n", __func__, sr); in stm32_rng_read()
222 err = stm32_rng_conceal_seed_error(rng); in stm32_rng_read()
225 dev_err(priv->dev, "Couldn't recover from seed error\n"); in stm32_rng_read()
226 retval = -ENOTRECOVERABLE; in stm32_rng_read()
233 if (WARN_ONCE((sr & RNG_SR_CEIS), "RNG clock too slow - %x\n", sr)) in stm32_rng_read()
234 writel_relaxed(0, priv->base + RNG_SR); in stm32_rng_read()
238 *(u32 *)data = readl_relaxed(priv->base + RNG_DR); in stm32_rng_read()
240 err = stm32_rng_conceal_seed_error(rng); in stm32_rng_read()
243 dev_err(priv->dev, "Couldn't recover from seed error"); in stm32_rng_read()
244 retval = -ENOTRECOVERABLE; in stm32_rng_read()
254 max -= sizeof(u32); in stm32_rng_read()
258 pm_runtime_mark_last_busy(priv->dev); in stm32_rng_read()
259 pm_runtime_put_sync_autosuspend(priv->dev); in stm32_rng_read()
261 return retval || !wait ? retval : -EIO; in stm32_rng_read()
264 static uint stm32_rng_clock_freq_restrain(struct hwrng *rng) in stm32_rng_clock_freq_restrain() argument
267 container_of(rng, struct stm32_rng_private, rng); in stm32_rng_clock_freq_restrain()
271 clock_rate = clk_get_rate(priv->clk_bulk[0].clk); in stm32_rng_clock_freq_restrain()
275 * No need to handle the case when clock-div > 0xF as it is physically in stm32_rng_clock_freq_restrain()
278 while ((clock_rate >> clock_div) > priv->data->max_clock_rate) in stm32_rng_clock_freq_restrain()
281 pr_debug("RNG clk rate : %lu\n", clk_get_rate(priv->clk_bulk[0].clk) >> clock_div); in stm32_rng_clock_freq_restrain()
286 static int stm32_rng_init(struct hwrng *rng) in stm32_rng_init() argument
289 container_of(rng, struct stm32_rng_private, rng); in stm32_rng_init()
293 err = clk_bulk_prepare_enable(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_init()
298 writel_relaxed(0, priv->base + RNG_SR); in stm32_rng_init()
300 reg = readl_relaxed(priv->base + RNG_CR); in stm32_rng_init()
303 * Keep default RNG configuration if none was specified. in stm32_rng_init()
306 if (priv->data->has_cond_reset && priv->data->cr) { in stm32_rng_init()
307 uint clock_div = stm32_rng_clock_freq_restrain(rng); in stm32_rng_init()
310 reg |= RNG_CR_CONDRST | (priv->data->cr & RNG_CR_ENTROPY_SRC_MASK) | in stm32_rng_init()
312 if (priv->ced) in stm32_rng_init()
316 writel_relaxed(reg, priv->base + RNG_CR); in stm32_rng_init()
319 writel_relaxed(priv->data->htcr, priv->base + RNG_HTCR); in stm32_rng_init()
320 writel_relaxed(priv->data->nscr & RNG_NSCR_MASK, priv->base + RNG_NSCR); in stm32_rng_init()
324 if (priv->lock_conf) in stm32_rng_init()
327 writel_relaxed(reg, priv->base + RNG_CR); in stm32_rng_init()
329 err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg, in stm32_rng_init()
333 clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_init()
334 dev_err(priv->dev, "%s: timeout %x!\n", __func__, reg); in stm32_rng_init()
335 return -EINVAL; in stm32_rng_init()
338 /* Handle all RNG versions by checking if conditional reset should be set */ in stm32_rng_init()
339 if (priv->data->has_cond_reset) in stm32_rng_init()
342 if (priv->ced) in stm32_rng_init()
347 writel_relaxed(reg, priv->base + RNG_CR); in stm32_rng_init()
349 if (priv->data->has_cond_reset) in stm32_rng_init()
354 writel_relaxed(reg, priv->base + RNG_CR); in stm32_rng_init()
357 err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_SR, reg, in stm32_rng_init()
361 clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_init()
362 dev_err(priv->dev, "%s: timeout:%x SR: %x!\n", __func__, err, reg); in stm32_rng_init()
364 return -EINVAL; in stm32_rng_init()
367 clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_init()
374 pm_runtime_disable(&ofdev->dev); in stm32_rng_remove()
382 reg = readl_relaxed(priv->base + RNG_CR); in stm32_rng_runtime_suspend()
384 writel_relaxed(reg, priv->base + RNG_CR); in stm32_rng_runtime_suspend()
386 clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_runtime_suspend()
396 err = clk_bulk_prepare_enable(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_suspend()
400 if (priv->data->has_cond_reset) { in stm32_rng_suspend()
401 priv->pm_conf.nscr = readl_relaxed(priv->base + RNG_NSCR); in stm32_rng_suspend()
402 priv->pm_conf.htcr = readl_relaxed(priv->base + RNG_HTCR); in stm32_rng_suspend()
405 /* Do not save that RNG is enabled as it will be handled at resume */ in stm32_rng_suspend()
406 priv->pm_conf.cr = readl_relaxed(priv->base + RNG_CR) & ~RNG_CR_RNGEN; in stm32_rng_suspend()
408 writel_relaxed(priv->pm_conf.cr, priv->base + RNG_CR); in stm32_rng_suspend()
410 clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_suspend()
421 err = clk_bulk_prepare_enable(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_runtime_resume()
426 writel_relaxed(0, priv->base + RNG_SR); in stm32_rng_runtime_resume()
428 reg = readl_relaxed(priv->base + RNG_CR); in stm32_rng_runtime_resume()
430 writel_relaxed(reg, priv->base + RNG_CR); in stm32_rng_runtime_resume()
441 err = clk_bulk_prepare_enable(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_resume()
446 writel_relaxed(0, priv->base + RNG_SR); in stm32_rng_resume()
448 if (priv->data->has_cond_reset) { in stm32_rng_resume()
455 writel_relaxed(priv->pm_conf.cr | RNG_CR_CONDRST, priv->base + RNG_CR); in stm32_rng_resume()
457 writel_relaxed(priv->pm_conf.nscr, priv->base + RNG_NSCR); in stm32_rng_resume()
458 writel_relaxed(priv->pm_conf.htcr, priv->base + RNG_HTCR); in stm32_rng_resume()
460 reg = readl_relaxed(priv->base + RNG_CR); in stm32_rng_resume()
463 writel_relaxed(reg, priv->base + RNG_CR); in stm32_rng_resume()
465 err = readl_relaxed_poll_timeout_atomic(priv->base + RNG_CR, reg, in stm32_rng_resume()
469 clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_resume()
470 dev_err(priv->dev, "%s: timeout:%x CR: %x!\n", __func__, err, reg); in stm32_rng_resume()
471 return -EINVAL; in stm32_rng_resume()
474 reg = priv->pm_conf.cr; in stm32_rng_resume()
476 writel_relaxed(reg, priv->base + RNG_CR); in stm32_rng_resume()
479 clk_bulk_disable_unprepare(priv->data->nb_clock, priv->clk_bulk); in stm32_rng_resume()
517 .compatible = "st,stm32mp25-rng",
521 .compatible = "st,stm32mp13-rng",
525 .compatible = "st,stm32-rng",
534 struct device *dev = &ofdev->dev; in stm32_rng_probe()
535 struct device_node *np = ofdev->dev.of_node; in stm32_rng_probe()
542 return -ENOMEM; in stm32_rng_probe()
544 priv->base = devm_platform_get_and_ioremap_resource(ofdev, 0, &res); in stm32_rng_probe()
545 if (IS_ERR(priv->base)) in stm32_rng_probe()
546 return PTR_ERR(priv->base); in stm32_rng_probe()
548 priv->rst = devm_reset_control_get(&ofdev->dev, NULL); in stm32_rng_probe()
549 if (!IS_ERR(priv->rst)) { in stm32_rng_probe()
550 reset_control_assert(priv->rst); in stm32_rng_probe()
552 reset_control_deassert(priv->rst); in stm32_rng_probe()
555 priv->ced = of_property_read_bool(np, "clock-error-detect"); in stm32_rng_probe()
556 priv->lock_conf = of_property_read_bool(np, "st,rng-lock-conf"); in stm32_rng_probe()
557 priv->dev = dev; in stm32_rng_probe()
559 priv->data = of_device_get_match_data(dev); in stm32_rng_probe()
560 if (!priv->data) in stm32_rng_probe()
561 return -ENODEV; in stm32_rng_probe()
565 priv->rng.name = dev_driver_string(dev); in stm32_rng_probe()
566 priv->rng.init = stm32_rng_init; in stm32_rng_probe()
567 priv->rng.read = stm32_rng_read; in stm32_rng_probe()
568 priv->rng.quality = 900; in stm32_rng_probe()
570 if (!priv->data->nb_clock || priv->data->nb_clock > 2) in stm32_rng_probe()
571 return -EINVAL; in stm32_rng_probe()
573 ret = devm_clk_bulk_get_all(dev, &priv->clk_bulk); in stm32_rng_probe()
574 if (ret != priv->data->nb_clock) in stm32_rng_probe()
575 return dev_err_probe(dev, -EINVAL, "Failed to get clocks: %d\n", ret); in stm32_rng_probe()
577 if (priv->data->nb_clock == 2) { in stm32_rng_probe()
578 const char *id = priv->clk_bulk[1].id; in stm32_rng_probe()
579 struct clk *clk = priv->clk_bulk[1].clk; in stm32_rng_probe()
581 if (!priv->clk_bulk[0].id || !priv->clk_bulk[1].id) in stm32_rng_probe()
582 return dev_err_probe(dev, -EINVAL, "Missing clock name\n"); in stm32_rng_probe()
584 if (strcmp(priv->clk_bulk[0].id, "core")) { in stm32_rng_probe()
585 priv->clk_bulk[1].id = priv->clk_bulk[0].id; in stm32_rng_probe()
586 priv->clk_bulk[1].clk = priv->clk_bulk[0].clk; in stm32_rng_probe()
587 priv->clk_bulk[0].id = id; in stm32_rng_probe()
588 priv->clk_bulk[0].clk = clk; in stm32_rng_probe()
596 return devm_hwrng_register(dev, &priv->rng); in stm32_rng_probe()
601 .name = "stm32-rng",
613 MODULE_DESCRIPTION("STMicroelectronics STM32 RNG device driver");