1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2019, Linaro Limited
6 #define LOG_CATEGORY UCLASS_RNG
14 #include <linux/bitops.h>
15 #include <linux/delay.h>
18 #include <linux/iopoll.h>
19 #include <linux/kernel.h>
22 #define RNG_CR_RNGEN BIT(2)
23 #define RNG_CR_CED BIT(5)
24 #define RNG_CR_CONDRST BIT(30)
27 #define RNG_SR_SEIS BIT(6)
28 #define RNG_SR_CEIS BIT(5)
29 #define RNG_SR_SECS BIT(2)
30 #define RNG_SR_DRDY BIT(0)
34 struct stm32_rng_data {
38 struct stm32_rng_plat {
42 const struct stm32_rng_data *data;
45 static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
50 struct stm32_rng_plat *pdata = dev_get_plat(dev);
53 retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
54 sr & RNG_SR_DRDY, 10000);
58 if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
60 clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS);
61 for (i = 0; i < 12; i++)
62 readl(pdata->base + RNG_DR);
63 if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) {
72 * Once the DRDY bit is set, the RNG_DR register can
73 * be read four consecutive times.
76 while (len && count) {
77 reg = readl(pdata->base + RNG_DR);
78 memcpy(data, ®, min(len, sizeof(u32)));
79 increment = min(len, sizeof(u32));
89 static int stm32_rng_init(struct stm32_rng_plat *pdata)
94 err = clk_enable(&pdata->clk);
98 cr = readl(pdata->base + RNG_CR);
102 if (pdata->data->has_cond_reset) {
103 cr |= RNG_CR_CONDRST;
104 writel(cr, pdata->base + RNG_CR);
105 cr &= ~RNG_CR_CONDRST;
106 writel(cr, pdata->base + RNG_CR);
107 err = readl_poll_timeout(pdata->base + RNG_CR, cr,
108 (!(cr & RNG_CR_CONDRST)), 10000);
113 /* clear error indicators */
114 writel(0, pdata->base + RNG_SR);
117 writel(cr, pdata->base + RNG_CR);
119 err = readl_poll_timeout(pdata->base + RNG_SR, sr,
120 sr & RNG_SR_DRDY, 10000);
124 static int stm32_rng_cleanup(struct stm32_rng_plat *pdata)
126 writel(0, pdata->base + RNG_CR);
128 return clk_disable(&pdata->clk);
131 static int stm32_rng_probe(struct udevice *dev)
133 struct stm32_rng_plat *pdata = dev_get_plat(dev);
135 pdata->data = (struct stm32_rng_data *)dev_get_driver_data(dev);
137 reset_assert(&pdata->rst);
139 reset_deassert(&pdata->rst);
141 return stm32_rng_init(pdata);
144 static int stm32_rng_remove(struct udevice *dev)
146 struct stm32_rng_plat *pdata = dev_get_plat(dev);
148 return stm32_rng_cleanup(pdata);
151 static int stm32_rng_of_to_plat(struct udevice *dev)
153 struct stm32_rng_plat *pdata = dev_get_plat(dev);
156 pdata->base = dev_read_addr(dev);
160 err = clk_get_by_index(dev, 0, &pdata->clk);
164 err = reset_get_by_index(dev, 0, &pdata->rst);
171 static const struct dm_rng_ops stm32_rng_ops = {
172 .read = stm32_rng_read,
175 static const struct stm32_rng_data stm32mp13_rng_data = {
176 .has_cond_reset = true,
179 static const struct stm32_rng_data stm32_rng_data = {
180 .has_cond_reset = false,
183 static const struct udevice_id stm32_rng_match[] = {
184 {.compatible = "st,stm32mp13-rng", .data = (ulong)&stm32mp13_rng_data},
185 {.compatible = "st,stm32-rng", .data = (ulong)&stm32_rng_data},
189 U_BOOT_DRIVER(stm32_rng) = {
192 .of_match = stm32_rng_match,
193 .ops = &stm32_rng_ops,
194 .probe = stm32_rng_probe,
195 .remove = stm32_rng_remove,
196 .plat_auto = sizeof(struct stm32_rng_plat),
197 .of_to_plat = stm32_rng_of_to_plat,