GNU Linux-libre 5.16.19-gnu
[releases.git] / drivers / crypto / gemini / sl3516-ce-rng.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * sl3516-ce-rng.c - hardware cryptographic offloader for SL3516 SoC.
4  *
5  * Copyright (C) 2021 Corentin Labbe <clabbe@baylibre.com>
6  *
7  * This file handle the RNG found in the SL3516 crypto engine
8  */
9 #include "sl3516-ce.h"
10 #include <linux/pm_runtime.h>
11 #include <linux/hw_random.h>
12
13 static int sl3516_ce_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
14 {
15         struct sl3516_ce_dev *ce;
16         u32 *data = buf;
17         size_t read = 0;
18         int err;
19
20         ce = container_of(rng, struct sl3516_ce_dev, trng);
21
22 #ifdef CONFIG_CRYPTO_DEV_SL3516_DEBUG
23         ce->hwrng_stat_req++;
24         ce->hwrng_stat_bytes += max;
25 #endif
26
27         err = pm_runtime_get_sync(ce->dev);
28         if (err < 0) {
29                 pm_runtime_put_noidle(ce->dev);
30                 return err;
31         }
32
33         while (read < max) {
34                 *data = readl(ce->base + IPSEC_RAND_NUM_REG);
35                 data++;
36                 read += 4;
37         }
38
39         pm_runtime_put(ce->dev);
40
41         return read;
42 }
43
44 int sl3516_ce_rng_register(struct sl3516_ce_dev *ce)
45 {
46         int ret;
47
48         ce->trng.name = "SL3516 Crypto Engine RNG";
49         ce->trng.read = sl3516_ce_rng_read;
50         ce->trng.quality = 700;
51
52         ret = hwrng_register(&ce->trng);
53         if (ret)
54                 dev_err(ce->dev, "Fail to register the RNG\n");
55         return ret;
56 }
57
58 void sl3516_ce_rng_unregister(struct sl3516_ce_dev *ce)
59 {
60         hwrng_unregister(&ce->trng);
61 }