Lines Matching +full:- +full:seed
1 // SPDX-License-Identifier: GPL-2.0
3 * exynos-rng.c - Random Number Generator driver for the Exynos
7 * Loosely based on old driver from drivers/char/hw_random/exynos-rng.c:
40 /* Five seed and output registers, each 4 bytes */
51 * Driver re-seeds itself with generated random numbers to hinder
52 * backtracking of the original seed.
54 * Time for next re-seed in ms.
89 return readl_relaxed(rng->mem + offset); in exynos_rng_readl()
94 writel_relaxed(val, rng->mem + offset); in exynos_rng_writel()
98 const u8 *seed, unsigned int slen) in exynos_rng_set_seed() argument
103 /* Round seed length because loop iterates over full register size */ in exynos_rng_set_seed()
107 return -EINVAL; in exynos_rng_set_seed()
112 val = seed[i] << 24; in exynos_rng_set_seed()
113 val |= seed[i + 1] << 16; in exynos_rng_set_seed()
114 val |= seed[i + 2] << 8; in exynos_rng_set_seed()
115 val |= seed[i + 3] << 0; in exynos_rng_set_seed()
122 dev_warn(rng->dev, "Seed setting not finished\n"); in exynos_rng_set_seed()
123 return -EIO; in exynos_rng_set_seed()
126 rng->last_seeding = jiffies; in exynos_rng_set_seed()
127 rng->bytes_seeding = 0; in exynos_rng_set_seed()
138 * On error: return -ERRNO.
146 if (rng->type == EXYNOS_PRNG_EXYNOS4) { in exynos_rng_get_random()
149 } else if (rng->type == EXYNOS_PRNG_EXYNOS5) { in exynos_rng_get_random()
155 EXYNOS_RNG_STATUS) & EXYNOS_RNG_STATUS_RNG_DONE) && --retry) in exynos_rng_get_random()
159 return -ETIMEDOUT; in exynos_rng_get_random()
165 memcpy_fromio(dst, rng->mem + EXYNOS_RNG_OUT_BASE, *read); in exynos_rng_get_random()
166 rng->bytes_seeding += *read; in exynos_rng_get_random()
171 /* Re-seed itself from time to time */
174 unsigned long next_seeding = rng->last_seeding + \ in exynos_rng_reseed()
178 u8 seed[EXYNOS_RNG_SEED_SIZE]; in exynos_rng_reseed() local
181 rng->bytes_seeding < EXYNOS_RNG_RESEED_BYTES) in exynos_rng_reseed()
184 if (exynos_rng_get_random(rng, seed, sizeof(seed), &read)) in exynos_rng_reseed()
187 exynos_rng_set_seed(rng, seed, read); in exynos_rng_reseed()
190 mutex_unlock(&rng->lock); in exynos_rng_reseed()
191 mutex_lock(&rng->lock); in exynos_rng_reseed()
199 struct exynos_rng_dev *rng = ctx->rng; in exynos_rng_generate()
203 ret = clk_prepare_enable(rng->clk); in exynos_rng_generate()
207 mutex_lock(&rng->lock); in exynos_rng_generate()
213 dlen -= read; in exynos_rng_generate()
218 mutex_unlock(&rng->lock); in exynos_rng_generate()
220 clk_disable_unprepare(rng->clk); in exynos_rng_generate()
225 static int exynos_rng_seed(struct crypto_rng *tfm, const u8 *seed, in exynos_rng_seed() argument
229 struct exynos_rng_dev *rng = ctx->rng; in exynos_rng_seed()
232 ret = clk_prepare_enable(rng->clk); in exynos_rng_seed()
236 mutex_lock(&rng->lock); in exynos_rng_seed()
237 ret = exynos_rng_set_seed(ctx->rng, seed, slen); in exynos_rng_seed()
238 mutex_unlock(&rng->lock); in exynos_rng_seed()
240 clk_disable_unprepare(rng->clk); in exynos_rng_seed()
249 ctx->rng = exynos_rng_dev; in exynos_rng_kcapi_init()
256 .seed = exynos_rng_seed,
274 return -EEXIST; in exynos_rng_probe()
276 rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); in exynos_rng_probe()
278 return -ENOMEM; in exynos_rng_probe()
280 rng->type = (uintptr_t)of_device_get_match_data(&pdev->dev); in exynos_rng_probe()
282 mutex_init(&rng->lock); in exynos_rng_probe()
284 rng->dev = &pdev->dev; in exynos_rng_probe()
285 rng->clk = devm_clk_get(&pdev->dev, "secss"); in exynos_rng_probe()
286 if (IS_ERR(rng->clk)) { in exynos_rng_probe()
287 dev_err(&pdev->dev, "Couldn't get clock.\n"); in exynos_rng_probe()
288 return PTR_ERR(rng->clk); in exynos_rng_probe()
291 rng->mem = devm_platform_ioremap_resource(pdev, 0); in exynos_rng_probe()
292 if (IS_ERR(rng->mem)) in exynos_rng_probe()
293 return PTR_ERR(rng->mem); in exynos_rng_probe()
301 dev_err(&pdev->dev, in exynos_rng_probe()
324 if (!rng->last_seeding) in exynos_rng_suspend()
327 rng->seed_save_len = 0; in exynos_rng_suspend()
328 ret = clk_prepare_enable(rng->clk); in exynos_rng_suspend()
332 mutex_lock(&rng->lock); in exynos_rng_suspend()
335 exynos_rng_get_random(rng, rng->seed_save, sizeof(rng->seed_save), in exynos_rng_suspend()
336 &(rng->seed_save_len)); in exynos_rng_suspend()
338 mutex_unlock(&rng->lock); in exynos_rng_suspend()
340 dev_dbg(rng->dev, "Stored %u bytes for seeding on system resume\n", in exynos_rng_suspend()
341 rng->seed_save_len); in exynos_rng_suspend()
343 clk_disable_unprepare(rng->clk); in exynos_rng_suspend()
354 if (!rng->last_seeding) in exynos_rng_resume()
357 ret = clk_prepare_enable(rng->clk); in exynos_rng_resume()
361 mutex_lock(&rng->lock); in exynos_rng_resume()
363 ret = exynos_rng_set_seed(rng, rng->seed_save, rng->seed_save_len); in exynos_rng_resume()
365 mutex_unlock(&rng->lock); in exynos_rng_resume()
367 clk_disable_unprepare(rng->clk); in exynos_rng_resume()
377 .compatible = "samsung,exynos4-rng",
380 .compatible = "samsung,exynos5250-prng",
389 .name = "exynos-rng",