1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2020 Fuzhou Rockchip Electronics Co., Ltd
4 */
5 #include <common.h>
6 #include <clk-uclass.h>
7 #include <dm.h>
8 #include <rng.h>
9 #include <asm/arch-rockchip/hardware.h>
10 #include <asm/io.h>
11 #include <linux/iopoll.h>
12 #include <linux/string.h>
13
14 #define RK_HW_RNG_MAX 32
15
16 #define _SBF(s, v) ((v) << (s))
17
18 /* start of CRYPTO V1 register define */
19 #define CRYPTO_V1_CTRL 0x0008
20 #define CRYPTO_V1_RNG_START BIT(8)
21 #define CRYPTO_V1_RNG_FLUSH BIT(9)
22
23 #define CRYPTO_V1_TRNG_CTRL 0x0200
24 #define CRYPTO_V1_OSC_ENABLE BIT(16)
25 #define CRYPTO_V1_TRNG_SAMPLE_PERIOD(x) (x)
26
27 #define CRYPTO_V1_TRNG_DOUT_0 0x0204
28 /* end of CRYPTO V1 register define */
29
30 /* start of CRYPTO V2 register define */
31 #define CRYPTO_V2_RNG_CTL 0x0400
32 #define CRYPTO_V2_RNG_64_BIT_LEN _SBF(4, 0x00)
33 #define CRYPTO_V2_RNG_128_BIT_LEN _SBF(4, 0x01)
34 #define CRYPTO_V2_RNG_192_BIT_LEN _SBF(4, 0x02)
35 #define CRYPTO_V2_RNG_256_BIT_LEN _SBF(4, 0x03)
36 #define CRYPTO_V2_RNG_FATESY_SOC_RING _SBF(2, 0x00)
37 #define CRYPTO_V2_RNG_SLOWER_SOC_RING_0 _SBF(2, 0x01)
38 #define CRYPTO_V2_RNG_SLOWER_SOC_RING_1 _SBF(2, 0x02)
39 #define CRYPTO_V2_RNG_SLOWEST_SOC_RING _SBF(2, 0x03)
40 #define CRYPTO_V2_RNG_ENABLE BIT(1)
41 #define CRYPTO_V2_RNG_START BIT(0)
42 #define CRYPTO_V2_RNG_SAMPLE_CNT 0x0404
43 #define CRYPTO_V2_RNG_DOUT_0 0x0410
44 /* end of CRYPTO V2 register define */
45
46 /* start of TRNG V1 register define */
47 #define TRNG_V1_CTRL 0x0000
48 #define TRNG_V1_CTRL_NOP _SBF(0, 0x00)
49 #define TRNG_V1_CTRL_RAND _SBF(0, 0x01)
50 #define TRNG_V1_CTRL_SEED _SBF(0, 0x02)
51
52 #define TRNG_V1_MODE 0x0008
53 #define TRNG_V1_MODE_128_BIT _SBF(3, 0x00)
54 #define TRNG_V1_MODE_256_BIT _SBF(3, 0x01)
55
56 #define TRNG_V1_IE 0x0010
57 #define TRNG_V1_IE_GLBL_EN BIT(31)
58 #define TRNG_V1_IE_SEED_DONE_EN BIT(1)
59 #define TRNG_V1_IE_RAND_RDY_EN BIT(0)
60
61 #define TRNG_V1_ISTAT 0x0014
62 #define TRNG_V1_ISTAT_RAND_RDY BIT(0)
63
64 /* RAND0 ~ RAND7 */
65 #define TRNG_V1_RAND0 0x0020
66 #define TRNG_V1_RAND7 0x003C
67
68 #define TRNG_V1_AUTO_RQSTS 0x0060
69
70 #define TRNG_V1_VERSION 0x00F0
71 #define TRNG_v1_VERSION_CODE 0x46BC
72 /* end of TRNG V1 register define */
73
74 /* start of RKRNG register define */
75 #define RKRNG_CTRL 0x0010
76 #define RKRNG_CTRL_INST_REQ BIT(0)
77 #define RKRNG_CTRL_RESEED_REQ BIT(1)
78 #define RKRNG_CTRL_TEST_REQ BIT(2)
79 #define RKRNG_CTRL_SW_DRNG_REQ BIT(3)
80 #define RKRNG_CTRL_SW_TRNG_REQ BIT(4)
81
82 #define RKRNG_STATE 0x0014
83 #define RKRNG_STATE_INST_ACK BIT(0)
84 #define RKRNG_STATE_RESEED_ACK BIT(1)
85 #define RKRNG_STATE_TEST_ACK BIT(2)
86 #define RKRNG_STATE_SW_DRNG_ACK BIT(3)
87 #define RKRNG_STATE_SW_TRNG_ACK BIT(4)
88
89 /* DRNG_DATA_0 ~ DNG_DATA_7 */
90 #define RKRNG_DRNG_DATA_0 0x0070
91 #define RKRNG_DRNG_DATA_7 0x008C
92
93 /* end of RKRNG register define */
94
95 #define RK_RNG_TIME_OUT 50000 /* max 50ms */
96
97 #define trng_write(pdata, pos, val) writel(val, (pdata)->base + (pos))
98 #define trng_read(pdata, pos) readl((pdata)->base + (pos))
99
100 struct rk_rng_soc_data {
101 int (*rk_rng_init)(struct udevice *dev);
102 int (*rk_rng_read)(struct udevice *dev, void *data, size_t len);
103 };
104
105 struct rk_rng_platdata {
106 fdt_addr_t base;
107 struct rk_rng_soc_data *soc_data;
108 struct clk hclk;
109 };
110
rk_rng_do_enable_clk(struct udevice * dev,int enable)111 static int rk_rng_do_enable_clk(struct udevice *dev, int enable)
112 {
113 struct rk_rng_platdata *pdata = dev_get_priv(dev);
114 int ret;
115
116 if (!pdata->hclk.dev)
117 return 0;
118
119 ret = enable ? clk_enable(&pdata->hclk) : clk_disable(&pdata->hclk);
120 if (ret == -ENOSYS || !ret)
121 return 0;
122
123 printf("rk rng: failed to %s clk, ret=%d\n",
124 enable ? "enable" : "disable", ret);
125
126 return ret;
127 }
128
rk_rng_enable_clk(struct udevice * dev)129 static int rk_rng_enable_clk(struct udevice *dev)
130 {
131 return rk_rng_do_enable_clk(dev, 1);
132 }
133
rk_rng_disable_clk(struct udevice * dev)134 static int rk_rng_disable_clk(struct udevice *dev)
135 {
136 return rk_rng_do_enable_clk(dev, 0);
137 }
138
rk_rng_read_regs(fdt_addr_t addr,void * buf,size_t size)139 static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size)
140 {
141 u32 count = RK_HW_RNG_MAX / sizeof(u32);
142 u32 reg, tmp_len;
143
144 if (size > RK_HW_RNG_MAX)
145 return -EINVAL;
146
147 while (size && count) {
148 reg = readl(addr);
149 tmp_len = min(size, sizeof(u32));
150 memcpy(buf, ®, tmp_len);
151 addr += sizeof(u32);
152 buf += tmp_len;
153 size -= tmp_len;
154 count--;
155 }
156
157 return 0;
158 }
159
cryptov1_rng_read(struct udevice * dev,void * data,size_t len)160 static int cryptov1_rng_read(struct udevice *dev, void *data, size_t len)
161 {
162 struct rk_rng_platdata *pdata = dev_get_priv(dev);
163 u32 reg = 0;
164 int retval;
165
166 if (len > RK_HW_RNG_MAX)
167 return -EINVAL;
168
169 /* enable osc_ring to get entropy, sample period is set as 100 */
170 writel(CRYPTO_V1_OSC_ENABLE | CRYPTO_V1_TRNG_SAMPLE_PERIOD(100),
171 pdata->base + CRYPTO_V1_TRNG_CTRL);
172
173 rk_clrsetreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START,
174 CRYPTO_V1_RNG_START);
175
176 retval = readl_poll_timeout(pdata->base + CRYPTO_V1_CTRL, reg,
177 !(reg & CRYPTO_V1_RNG_START),
178 RK_RNG_TIME_OUT);
179 if (retval)
180 goto exit;
181
182 rk_rng_read_regs(pdata->base + CRYPTO_V1_TRNG_DOUT_0, data, len);
183
184 exit:
185 /* close TRNG */
186 rk_clrreg(pdata->base + CRYPTO_V1_CTRL, CRYPTO_V1_RNG_START);
187
188 return 0;
189 }
190
cryptov2_rng_read(struct udevice * dev,void * data,size_t len)191 static int cryptov2_rng_read(struct udevice *dev, void *data, size_t len)
192 {
193 struct rk_rng_platdata *pdata = dev_get_priv(dev);
194 u32 reg = 0;
195 int retval;
196
197 if (len > RK_HW_RNG_MAX)
198 return -EINVAL;
199
200 /* enable osc_ring to get entropy, sample period is set as 100 */
201 writel(100, pdata->base + CRYPTO_V2_RNG_SAMPLE_CNT);
202
203 reg |= CRYPTO_V2_RNG_256_BIT_LEN;
204 reg |= CRYPTO_V2_RNG_SLOWER_SOC_RING_0;
205 reg |= CRYPTO_V2_RNG_ENABLE;
206 reg |= CRYPTO_V2_RNG_START;
207
208 rk_clrsetreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff, reg);
209
210 retval = readl_poll_timeout(pdata->base + CRYPTO_V2_RNG_CTL, reg,
211 !(reg & CRYPTO_V2_RNG_START),
212 RK_RNG_TIME_OUT);
213 if (retval)
214 goto exit;
215
216 rk_rng_read_regs(pdata->base + CRYPTO_V2_RNG_DOUT_0, data, len);
217
218 exit:
219 /* close TRNG */
220 rk_clrreg(pdata->base + CRYPTO_V2_RNG_CTL, 0xffff);
221
222 return retval;
223 }
224
trngv1_init(struct udevice * dev)225 static int trngv1_init(struct udevice *dev)
226 {
227 u32 status, version;
228 u32 auto_reseed_cnt = 1000;
229 struct rk_rng_platdata *pdata = dev_get_priv(dev);
230
231 version = trng_read(pdata, TRNG_V1_VERSION);
232 if (version != TRNG_v1_VERSION_CODE) {
233 printf("wrong trng version, expected = %08x, actual = %08x",
234 TRNG_V1_VERSION, version);
235 return -EFAULT;
236 }
237
238 /* wait in case of RND_RDY triggered at firs power on */
239 readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, status,
240 (status & TRNG_V1_ISTAT_RAND_RDY),
241 RK_RNG_TIME_OUT);
242
243 /* clear RAND_RDY flag for first power on */
244 trng_write(pdata, TRNG_V1_ISTAT, status);
245
246 /* auto reseed after (auto_reseed_cnt * 16) byte rand generate */
247 trng_write(pdata, TRNG_V1_AUTO_RQSTS, auto_reseed_cnt);
248
249 return 0;
250 }
251
trngv1_rng_read(struct udevice * dev,void * data,size_t len)252 static int trngv1_rng_read(struct udevice *dev, void *data, size_t len)
253 {
254 struct rk_rng_platdata *pdata = dev_get_priv(dev);
255 u32 reg = 0;
256 int retval;
257
258 if (len > RK_HW_RNG_MAX)
259 return -EINVAL;
260
261 trng_write(pdata, TRNG_V1_MODE, TRNG_V1_MODE_256_BIT);
262 trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_RAND);
263
264 retval = readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, reg,
265 (reg & TRNG_V1_ISTAT_RAND_RDY),
266 RK_RNG_TIME_OUT);
267 /* clear ISTAT */
268 trng_write(pdata, TRNG_V1_ISTAT, reg);
269
270 if (retval)
271 goto exit;
272
273 rk_rng_read_regs(pdata->base + TRNG_V1_RAND0, data, len);
274
275 exit:
276 /* close TRNG */
277 trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_NOP);
278
279 return retval;
280 }
281
rkrng_init(struct udevice * dev)282 static int rkrng_init(struct udevice *dev)
283 {
284 struct rk_rng_platdata *pdata = dev_get_priv(dev);
285 u32 reg = 0;
286
287 rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
288
289 reg = trng_read(pdata, RKRNG_STATE);
290 trng_write(pdata, RKRNG_STATE, reg);
291
292 return 0;
293 }
294
rkrng_rng_read(struct udevice * dev,void * data,size_t len)295 static int rkrng_rng_read(struct udevice *dev, void *data, size_t len)
296 {
297 struct rk_rng_platdata *pdata = dev_get_priv(dev);
298 u32 reg = 0;
299 int retval;
300
301 if (len > RK_HW_RNG_MAX)
302 return -EINVAL;
303
304 rk_rng_enable_clk(dev);
305
306 reg = RKRNG_CTRL_SW_DRNG_REQ;
307
308 rk_clrsetreg(pdata->base + RKRNG_CTRL, 0xffff, reg);
309
310 retval = readl_poll_timeout(pdata->base + RKRNG_STATE, reg,
311 (reg & RKRNG_STATE_SW_DRNG_ACK),
312 RK_RNG_TIME_OUT);
313 if (retval)
314 goto exit;
315
316 trng_write(pdata, RKRNG_STATE, reg);
317
318 rk_rng_read_regs(pdata->base + RKRNG_DRNG_DATA_0, data, len);
319
320 exit:
321 /* close TRNG */
322 rk_clrreg(pdata->base + RKRNG_CTRL, 0xffff);
323
324 rk_rng_disable_clk(dev);
325
326 return retval;
327 }
328
rockchip_rng_read(struct udevice * dev,void * data,size_t len)329 static int rockchip_rng_read(struct udevice *dev, void *data, size_t len)
330 {
331 unsigned char *buf = data;
332 unsigned int i;
333 int ret = -EIO;
334
335 struct rk_rng_platdata *pdata = dev_get_priv(dev);
336
337 if (!len)
338 return 0;
339
340 if (!pdata->soc_data || !pdata->soc_data->rk_rng_read)
341 return -EINVAL;
342
343 for (i = 0; i < len / RK_HW_RNG_MAX; i++, buf += RK_HW_RNG_MAX) {
344 ret = pdata->soc_data->rk_rng_read(dev, buf, RK_HW_RNG_MAX);
345 if (ret)
346 goto exit;
347 }
348
349 if (len % RK_HW_RNG_MAX)
350 ret = pdata->soc_data->rk_rng_read(dev, buf,
351 len % RK_HW_RNG_MAX);
352
353 exit:
354 return ret;
355 }
356
rockchip_rng_ofdata_to_platdata(struct udevice * dev)357 static int rockchip_rng_ofdata_to_platdata(struct udevice *dev)
358 {
359 struct rk_rng_platdata *pdata = dev_get_priv(dev);
360
361 memset(pdata, 0x00, sizeof(*pdata));
362
363 pdata->base = (fdt_addr_t)dev_read_addr_ptr(dev);
364 if (!pdata->base)
365 return -ENOMEM;
366
367 clk_get_by_index(dev, 0, &pdata->hclk);
368
369 return 0;
370 }
371
rockchip_rng_probe(struct udevice * dev)372 static int rockchip_rng_probe(struct udevice *dev)
373 {
374 struct rk_rng_platdata *pdata = dev_get_priv(dev);
375 int ret = 0;
376
377 pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev);
378
379 if (pdata->soc_data->rk_rng_init)
380 ret = pdata->soc_data->rk_rng_init(dev);
381
382 return ret;
383 }
384
385 static const struct rk_rng_soc_data cryptov1_soc_data = {
386 .rk_rng_read = cryptov1_rng_read,
387 };
388
389 static const struct rk_rng_soc_data cryptov2_soc_data = {
390 .rk_rng_read = cryptov2_rng_read,
391 };
392
393 static const struct rk_rng_soc_data trngv1_soc_data = {
394 .rk_rng_init = trngv1_init,
395 .rk_rng_read = trngv1_rng_read,
396 };
397
398 static const struct rk_rng_soc_data rkrng_soc_data = {
399 .rk_rng_init = rkrng_init,
400 .rk_rng_read = rkrng_rng_read,
401 };
402
403 static const struct dm_rng_ops rockchip_rng_ops = {
404 .read = rockchip_rng_read,
405 };
406
407 static const struct udevice_id rockchip_rng_match[] = {
408 {
409 .compatible = "rockchip,cryptov1-rng",
410 .data = (ulong)&cryptov1_soc_data,
411 },
412 {
413 .compatible = "rockchip,cryptov2-rng",
414 .data = (ulong)&cryptov2_soc_data,
415 },
416 {
417 .compatible = "rockchip,trngv1",
418 .data = (ulong)&trngv1_soc_data,
419 },
420 {
421 .compatible = "rockchip,rkrng",
422 .data = (ulong)&rkrng_soc_data,
423 },
424 {},
425 };
426
427 U_BOOT_DRIVER(rockchip_rng) = {
428 .name = "rockchip-rng",
429 .id = UCLASS_RNG,
430 .of_match = rockchip_rng_match,
431 .ops = &rockchip_rng_ops,
432 .probe = rockchip_rng_probe,
433 .ofdata_to_platdata = rockchip_rng_ofdata_to_platdata,
434 .priv_auto_alloc_size = sizeof(struct rk_rng_platdata),
435 };
436