1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2019, Linaro Limited
12 #include <linux/bitops.h>
13 #include <linux/delay.h>
16 #include <linux/iopoll.h>
17 #include <linux/kernel.h>
20 #define RNG_CR_RNGEN BIT(2)
21 #define RNG_CR_CED BIT(5)
24 #define RNG_SR_SEIS BIT(6)
25 #define RNG_SR_CEIS BIT(5)
26 #define RNG_SR_SECS BIT(2)
27 #define RNG_SR_DRDY BIT(0)
31 struct stm32_rng_platdata {
37 static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
42 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
45 retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
46 sr & RNG_SR_DRDY, 10000);
50 if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
52 clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS);
53 for (i = 0; i < 12; i++)
54 readl(pdata->base + RNG_DR);
55 if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) {
64 * Once the DRDY bit is set, the RNG_DR register can
65 * be read four consecutive times.
68 while (len && count) {
69 reg = readl(pdata->base + RNG_DR);
70 memcpy(data, ®, min(len, sizeof(u32)));
71 increment = min(len, sizeof(u32));
81 static int stm32_rng_init(struct stm32_rng_platdata *pdata)
85 err = clk_enable(&pdata->clk);
90 writel(RNG_CR_RNGEN | RNG_CR_CED, pdata->base + RNG_CR);
92 /* clear error indicators */
93 writel(0, pdata->base + RNG_SR);
98 static int stm32_rng_cleanup(struct stm32_rng_platdata *pdata)
100 writel(0, pdata->base + RNG_CR);
102 return clk_disable(&pdata->clk);
105 static int stm32_rng_probe(struct udevice *dev)
107 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
109 reset_assert(&pdata->rst);
111 reset_deassert(&pdata->rst);
113 return stm32_rng_init(pdata);
116 static int stm32_rng_remove(struct udevice *dev)
118 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
120 return stm32_rng_cleanup(pdata);
123 static int stm32_rng_ofdata_to_platdata(struct udevice *dev)
125 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
128 pdata->base = dev_read_addr(dev);
132 err = clk_get_by_index(dev, 0, &pdata->clk);
136 err = reset_get_by_index(dev, 0, &pdata->rst);
143 static const struct dm_rng_ops stm32_rng_ops = {
144 .read = stm32_rng_read,
147 static const struct udevice_id stm32_rng_match[] = {
149 .compatible = "st,stm32-rng",
154 U_BOOT_DRIVER(stm32_rng) = {
157 .of_match = stm32_rng_match,
158 .ops = &stm32_rng_ops,
159 .probe = stm32_rng_probe,
160 .remove = stm32_rng_remove,
161 .platdata_auto_alloc_size = sizeof(struct stm32_rng_platdata),
162 .ofdata_to_platdata = stm32_rng_ofdata_to_platdata,