1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (c) 2019, Linaro Limited
13 #include <linux/iopoll.h>
14 #include <linux/kernel.h>
17 #define RNG_CR_RNGEN BIT(2)
18 #define RNG_CR_CED BIT(5)
21 #define RNG_SR_SEIS BIT(6)
22 #define RNG_SR_CEIS BIT(5)
23 #define RNG_SR_SECS BIT(2)
24 #define RNG_SR_DRDY BIT(0)
28 struct stm32_rng_platdata {
34 static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
39 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
42 retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
43 sr & RNG_SR_DRDY, 10000);
47 if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
49 clrbits_le32(pdata->base + RNG_SR, RNG_SR_SEIS);
50 for (i = 0; i < 12; i++)
51 readl(pdata->base + RNG_DR);
52 if (readl(pdata->base + RNG_SR) & RNG_SR_SEIS) {
61 * Once the DRDY bit is set, the RNG_DR register can
62 * be read four consecutive times.
65 while (len && count) {
66 reg = readl(pdata->base + RNG_DR);
67 memcpy(data, ®, min(len, sizeof(u32)));
68 increment = min(len, sizeof(u32));
78 static int stm32_rng_init(struct stm32_rng_platdata *pdata)
82 err = clk_enable(&pdata->clk);
87 writel(RNG_CR_RNGEN | RNG_CR_CED, pdata->base + RNG_CR);
89 /* clear error indicators */
90 writel(0, pdata->base + RNG_SR);
95 static int stm32_rng_cleanup(struct stm32_rng_platdata *pdata)
97 writel(0, pdata->base + RNG_CR);
99 return clk_disable(&pdata->clk);
102 static int stm32_rng_probe(struct udevice *dev)
104 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
106 reset_assert(&pdata->rst);
108 reset_deassert(&pdata->rst);
110 return stm32_rng_init(pdata);
113 static int stm32_rng_remove(struct udevice *dev)
115 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
117 return stm32_rng_cleanup(pdata);
120 static int stm32_rng_ofdata_to_platdata(struct udevice *dev)
122 struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
125 pdata->base = dev_read_addr(dev);
129 err = clk_get_by_index(dev, 0, &pdata->clk);
133 err = reset_get_by_index(dev, 0, &pdata->rst);
140 static const struct dm_rng_ops stm32_rng_ops = {
141 .read = stm32_rng_read,
144 static const struct udevice_id stm32_rng_match[] = {
146 .compatible = "st,stm32-rng",
151 U_BOOT_DRIVER(stm32_rng) = {
154 .of_match = stm32_rng_match,
155 .ops = &stm32_rng_ops,
156 .probe = stm32_rng_probe,
157 .remove = stm32_rng_remove,
158 .platdata_auto_alloc_size = sizeof(struct stm32_rng_platdata),
159 .ofdata_to_platdata = stm32_rng_ofdata_to_platdata,