]> Git Repo - u-boot.git/blob - drivers/rng/stm32mp1_rng.c
drivers: led: bcm6858: set the correct led polarity register
[u-boot.git] / drivers / rng / stm32mp1_rng.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2019, Linaro Limited
4  */
5
6 #define LOG_CATEGORY UCLASS_RNG
7
8 #include <common.h>
9 #include <clk.h>
10 #include <dm.h>
11 #include <log.h>
12 #include <reset.h>
13 #include <rng.h>
14 #include <linux/bitops.h>
15 #include <linux/delay.h>
16
17 #include <asm/io.h>
18 #include <linux/iopoll.h>
19 #include <linux/kernel.h>
20
21 #define RNG_CR 0x00
22 #define RNG_CR_RNGEN BIT(2)
23 #define RNG_CR_CED BIT(5)
24
25 #define RNG_SR 0x04
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)
30
31 #define RNG_DR 0x08
32
33 struct stm32_rng_platdata {
34         fdt_addr_t base;
35         struct clk clk;
36         struct reset_ctl rst;
37 };
38
39 static int stm32_rng_read(struct udevice *dev, void *data, size_t len)
40 {
41         int retval, i;
42         u32 sr, count, reg;
43         size_t increment;
44         struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
45
46         while (len > 0) {
47                 retval = readl_poll_timeout(pdata->base + RNG_SR, sr,
48                                             sr & RNG_SR_DRDY, 10000);
49                 if (retval)
50                         return retval;
51
52                 if (sr & (RNG_SR_SEIS | RNG_SR_SECS)) {
53                         /* As per SoC TRM */
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) {
58                                 log_err("RNG Noise");
59                                 return -EIO;
60                         }
61                         /* start again */
62                         continue;
63                 }
64
65                 /*
66                  * Once the DRDY bit is set, the RNG_DR register can
67                  * be read four consecutive times.
68                  */
69                 count = 4;
70                 while (len && count) {
71                         reg = readl(pdata->base + RNG_DR);
72                         memcpy(data, &reg, min(len, sizeof(u32)));
73                         increment = min(len, sizeof(u32));
74                         data += increment;
75                         len -= increment;
76                         count--;
77                 }
78         }
79
80         return 0;
81 }
82
83 static int stm32_rng_init(struct stm32_rng_platdata *pdata)
84 {
85         int err;
86
87         err = clk_enable(&pdata->clk);
88         if (err)
89                 return err;
90
91         /* Disable CED */
92         writel(RNG_CR_RNGEN | RNG_CR_CED, pdata->base + RNG_CR);
93
94         /* clear error indicators */
95         writel(0, pdata->base + RNG_SR);
96
97         return 0;
98 }
99
100 static int stm32_rng_cleanup(struct stm32_rng_platdata *pdata)
101 {
102         writel(0, pdata->base + RNG_CR);
103
104         return clk_disable(&pdata->clk);
105 }
106
107 static int stm32_rng_probe(struct udevice *dev)
108 {
109         struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
110
111         reset_assert(&pdata->rst);
112         udelay(20);
113         reset_deassert(&pdata->rst);
114
115         return stm32_rng_init(pdata);
116 }
117
118 static int stm32_rng_remove(struct udevice *dev)
119 {
120         struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
121
122         return stm32_rng_cleanup(pdata);
123 }
124
125 static int stm32_rng_ofdata_to_platdata(struct udevice *dev)
126 {
127         struct stm32_rng_platdata *pdata = dev_get_platdata(dev);
128         int err;
129
130         pdata->base = dev_read_addr(dev);
131         if (!pdata->base)
132                 return -ENOMEM;
133
134         err = clk_get_by_index(dev, 0, &pdata->clk);
135         if (err)
136                 return err;
137
138         err = reset_get_by_index(dev, 0, &pdata->rst);
139         if (err)
140                 return err;
141
142         return 0;
143 }
144
145 static const struct dm_rng_ops stm32_rng_ops = {
146         .read = stm32_rng_read,
147 };
148
149 static const struct udevice_id stm32_rng_match[] = {
150         {
151                 .compatible = "st,stm32-rng",
152         },
153         {},
154 };
155
156 U_BOOT_DRIVER(stm32_rng) = {
157         .name = "stm32-rng",
158         .id = UCLASS_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,
165 };
This page took 0.036366 seconds and 4 git commands to generate.