| // SPDX-License-Identifier: GPL-2.0 |
| /* |
| * sl3516-ce-rng.c - hardware cryptographic offloader for SL3516 SoC. |
| * |
| * Copyright (C) 2021 Corentin Labbe <clabbe@baylibre.com> |
| * |
| * This file handle the RNG found in the SL3516 crypto engine |
| */ |
| #include "sl3516-ce.h" |
| #include <linux/pm_runtime.h> |
| #include <linux/hw_random.h> |
| |
| static int sl3516_ce_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait) |
| { |
| struct sl3516_ce_dev *ce; |
| u32 *data = buf; |
| size_t read = 0; |
| int err; |
| |
| ce = container_of(rng, struct sl3516_ce_dev, trng); |
| |
| #ifdef CONFIG_CRYPTO_DEV_SL3516_DEBUG |
| ce->hwrng_stat_req++; |
| ce->hwrng_stat_bytes += max; |
| #endif |
| |
| err = pm_runtime_get_sync(ce->dev); |
| if (err < 0) { |
| pm_runtime_put_noidle(ce->dev); |
| return err; |
| } |
| |
| while (read < max) { |
| *data = readl(ce->base + IPSEC_RAND_NUM_REG); |
| data++; |
| read += 4; |
| } |
| |
| pm_runtime_put(ce->dev); |
| |
| return read; |
| } |
| |
| int sl3516_ce_rng_register(struct sl3516_ce_dev *ce) |
| { |
| int ret; |
| |
| ce->trng.name = "SL3516 Crypto Engine RNG"; |
| ce->trng.read = sl3516_ce_rng_read; |
| ce->trng.quality = 700; |
| |
| ret = hwrng_register(&ce->trng); |
| if (ret) |
| dev_err(ce->dev, "Fail to register the RNG\n"); |
| return ret; |
| } |
| |
| void sl3516_ce_rng_unregister(struct sl3516_ce_dev *ce) |
| { |
| hwrng_unregister(&ce->trng); |
| } |