1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2019, Linaro Limited
14 #include <linux/iopoll.h>
15 #include <linux/kernel.h>
18 #define RNG_CR_RNGEN BIT(2)
19 #define RNG_CR_CED BIT(5)
22 #define RNG_SR_SEIS BIT(6)
23 #define RNG_SR_CEIS BIT(5)
24 #define RNG_SR_SECS BIT(2)
25 #define RNG_SR_DRDY BIT(0)
29 struct stm32_rng_platdata {
35 static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
40 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
43 retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
44 sr & RNG_SR_DRDY, 10000);
48 if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
50 clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS);
51 for (i = 0; i < 12; i++)
52 readl(pdata->base + RNG_DR);
53 if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) {
62 * Once the DRDY bit is set, the RNG_DR register can
63 * be read four consecutive times.
66 while (len && count) {
67 reg = readl(pdata->base + RNG_DR);
68 memcpy(data, ®, min(len, sizeof(u32)));
69 increment = min(len, sizeof(u32));
79 static int stm32_rng_init(struct stm32_rng_platdata *pdata)
83 err = clk_enable(&pdata->clk);
88 writel(RNG_CR_RNGEN | RNG_CR_CED, pdata->base + RNG_CR);
90 /* clear error indicators */
91 writel(0, pdata->base + RNG_SR);
96 static int stm32_rng_cleanup(struct stm32_rng_platdata *pdata)
98 writel(0, pdata->base + RNG_CR);
100 return clk_disable(&pdata->clk);
103 static int stm32_rng_probe(struct udevice *dev)
105 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
107 reset_assert(&pdata->rst);
109 reset_deassert(&pdata->rst);
111 return stm32_rng_init(pdata);
114 static int stm32_rng_remove(struct udevice *dev)
116 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
118 return stm32_rng_cleanup(pdata);
121 static int stm32_rng_ofdata_to_platdata(struct udevice *dev)
123 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
126 pdata->base = dev_read_addr(dev);
130 err = clk_get_by_index(dev, 0, &pdata->clk);
134 err = reset_get_by_index(dev, 0, &pdata->rst);
141 static const struct dm_rng_ops stm32_rng_ops = {
142 .read = stm32_rng_read,
145 static const struct udevice_id stm32_rng_match[] = {
147 .compatible = "st,stm32-rng",
152 U_BOOT_DRIVER(stm32_rng) = {
155 .of_match = stm32_rng_match,
156 .ops = &stm32_rng_ops,
157 .probe = stm32_rng_probe,
158 .remove = stm32_rng_remove,
159 .platdata_auto_alloc_size = sizeof(struct stm32_rng_platdata),
160 .ofdata_to_platdata = stm32_rng_ofdata_to_platdata,