1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2019, Linaro Limited
12 #include <linux/delay.h>
15 #include <linux/iopoll.h>
16 #include <linux/kernel.h>
19 #define RNG_CR_RNGEN BIT(2)
20 #define RNG_CR_CED BIT(5)
23 #define RNG_SR_SEIS BIT(6)
24 #define RNG_SR_CEIS BIT(5)
25 #define RNG_SR_SECS BIT(2)
26 #define RNG_SR_DRDY BIT(0)
30 struct stm32_rng_platdata {
36 static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
41 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
44 retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
45 sr & RNG_SR_DRDY, 10000);
49 if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
51 clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS);
52 for (i = 0; i < 12; i++)
53 readl(pdata->base + RNG_DR);
54 if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) {
63 * Once the DRDY bit is set, the RNG_DR register can
64 * be read four consecutive times.
67 while (len && count) {
68 reg = readl(pdata->base + RNG_DR);
69 memcpy(data, ®, min(len, sizeof(u32)));
70 increment = min(len, sizeof(u32));
80 static int stm32_rng_init(struct stm32_rng_platdata *pdata)
84 err = clk_enable(&pdata->clk);
89 writel(RNG_CR_RNGEN | RNG_CR_CED, pdata->base + RNG_CR);
91 /* clear error indicators */
92 writel(0, pdata->base + RNG_SR);
97 static int stm32_rng_cleanup(struct stm32_rng_platdata *pdata)
99 writel(0, pdata->base + RNG_CR);
101 return clk_disable(&pdata->clk);
104 static int stm32_rng_probe(struct udevice *dev)
106 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
108 reset_assert(&pdata->rst);
110 reset_deassert(&pdata->rst);
112 return stm32_rng_init(pdata);
115 static int stm32_rng_remove(struct udevice *dev)
117 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
119 return stm32_rng_cleanup(pdata);
122 static int stm32_rng_ofdata_to_platdata(struct udevice *dev)
124 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
127 pdata->base = dev_read_addr(dev);
131 err = clk_get_by_index(dev, 0, &pdata->clk);
135 err = reset_get_by_index(dev, 0, &pdata->rst);
142 static const struct dm_rng_ops stm32_rng_ops = {
143 .read = stm32_rng_read,
146 static const struct udevice_id stm32_rng_match[] = {
148 .compatible = "st,stm32-rng",
153 U_BOOT_DRIVER(stm32_rng) = {
156 .of_match = stm32_rng_match,
157 .ops = &stm32_rng_ops,
158 .probe = stm32_rng_probe,
159 .remove = stm32_rng_remove,
160 .platdata_auto_alloc_size = sizeof(struct stm32_rng_platdata),
161 .ofdata_to_platdata = stm32_rng_ofdata_to_platdata,