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)
26 #define RNG_SR_SEIS BIT(6)
27 #define RNG_SR_CEIS BIT(5)
28 #define RNG_SR_SECS BIT(2)
29 #define RNG_SR_DRDY BIT(0)
33 struct stm32_rng_platdata {
39 static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
44 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
47 retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
48 sr & RNG_SR_DRDY, 10000);
52 if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
54 clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS);
55 for (i = 0; i < 12; i++)
56 readl(pdata->base + RNG_DR);
57 if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) {
66 * Once the DRDY bit is set, the RNG_DR register can
67 * be read four consecutive times.
70 while (len && count) {
71 reg = readl(pdata->base + RNG_DR);
72 memcpy(data, ®, min(len, sizeof(u32)));
73 increment = min(len, sizeof(u32));
83 static int stm32_rng_init(struct stm32_rng_platdata *pdata)
87 err = clk_enable(&pdata->clk);
92 writel(RNG_CR_RNGEN | RNG_CR_CED, pdata->base + RNG_CR);
94 /* clear error indicators */
95 writel(0, pdata->base + RNG_SR);
100 static int stm32_rng_cleanup(struct stm32_rng_platdata *pdata)
102 writel(0, pdata->base + RNG_CR);
104 return clk_disable(&pdata->clk);
107 static int stm32_rng_probe(struct udevice *dev)
109 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
111 reset_assert(&pdata->rst);
113 reset_deassert(&pdata->rst);
115 return stm32_rng_init(pdata);
118 static int stm32_rng_remove(struct udevice *dev)
120 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
122 return stm32_rng_cleanup(pdata);
125 static int stm32_rng_ofdata_to_platdata(struct udevice *dev)
127 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
130 pdata->base = dev_read_addr(dev);
134 err = clk_get_by_index(dev, 0, &pdata->clk);
138 err = reset_get_by_index(dev, 0, &pdata->rst);
145 static const struct dm_rng_ops stm32_rng_ops = {
146 .read = stm32_rng_read,
149 static const struct udevice_id stm32_rng_match[] = {
151 .compatible = "st,stm32-rng",
156 U_BOOT_DRIVER(stm32_rng) = {
159 .of_match = stm32_rng_match,
160 .ops = &stm32_rng_ops,
161 .probe = stm32_rng_probe,
162 .remove = stm32_rng_remove,
163 .platdata_auto_alloc_size = sizeof(struct stm32_rng_platdata),
164 .ofdata_to_platdata = stm32_rng_ofdata_to_platdata,