#include <linux/hw_random.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
#define RNG_CR_RNGEN BIT(2)
#define RNG_CR_CED BIT(5)
#define RNG_SR_SEIS BIT(6)
#define RNG_SR_CEIS BIT(5)
#define RNG_SR_DRDY BIT(0)
struct stm32_rng_private {
struct reset_control *rst;
static int stm32_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
struct stm32_rng_private *priv =
container_of(rng, struct stm32_rng_private, rng);
pm_runtime_get_sync((struct device *) priv->rng.priv);
while (max > sizeof(u32)) {
sr = readl_relaxed(priv->base + RNG_SR);
retval = readl_relaxed_poll_timeout_atomic(priv->base
dev_err((struct device *)priv->rng.priv,
"%s: timeout %x!\n", __func__, sr);
if (WARN_ONCE(sr & (RNG_SR_SEIS | RNG_SR_CEIS),
"bad RNG status - %x\n", sr))
writel_relaxed(0, priv->base + RNG_SR);
*(u32 *)data = readl_relaxed(priv->base + RNG_DR);
pm_runtime_mark_last_busy((struct device *) priv->rng.priv);
pm_runtime_put_sync_autosuspend((struct device *) priv->rng.priv);
return retval || !wait ? retval : -EIO;
static int stm32_rng_init(struct hwrng *rng)