1 /*
2  * Copyright (c) 2017 - 2020, Broadcom
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <common/debug.h>
8 #include <drivers/delay_timer.h>
9 #include <lib/mmio.h>
10 #include <platform_def.h>
11 
12 #define RNG_CTRL_REG		(RNG_BASE_ADDR + 0x00)
13 #define RNG_CTRL_MASK		0x00001FFF
14 #define RNG_CTRL_ENABLE		0x00000001
15 #define RNG_CTRL_DISABLE	0x00000000
16 
17 #define RNG_SOFT_RESET_REG	(RNG_BASE_ADDR + 0x04)
18 #define RNG_SOFT_RESET_MASK	0x00000001
19 
20 #define RNG_FIFO_DATA_REG	(RNG_BASE_ADDR + 0x20)
21 
22 #define RNG_FIFO_COUNT_REG	(RNG_BASE_ADDR + 0x24)
23 #define RNG_FIFO_COUNT_MASK	0x000000FF
24 
25 #define RNG_FIFO_WORDS_MAX	16
26 #define MAX_WAIT_COUNT_50US	20000
27 
28 
rng_reset(void)29 static void rng_reset(void)
30 {
31 	/* Disable RBG */
32 	mmio_clrbits_32(RNG_CTRL_REG, RNG_CTRL_MASK);
33 
34 	/* Reset RNG and RBG */
35 	mmio_setbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
36 
37 	/* Take all out of reset */
38 	mmio_clrbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK);
39 }
40 
rng_enable(void)41 static void rng_enable(void)
42 {
43 	/* Setup RNG. */
44 	mmio_clrsetbits_32(RNG_CTRL_REG, RNG_CTRL_MASK, RNG_CTRL_ENABLE);
45 }
46 
rng_init(void)47 int rng_init(void)
48 {
49 	rng_reset();
50 
51 	rng_enable();
52 
53 	return 0;
54 }
55 
rng_read(uint32_t * p_out,uint32_t * words_read)56 int rng_read(uint32_t *p_out, uint32_t *words_read)
57 {
58 	uint32_t available_words;
59 	uint32_t i;
60 	uint32_t word_processed = 0;
61 	uint32_t wait_count = MAX_WAIT_COUNT_50US;
62 
63 	if (*words_read == 0) {
64 		ERROR("RNG Parameter: No word requested\n");
65 		return -1;
66 	}
67 
68 	do {
69 		available_words = mmio_read_32(RNG_FIFO_COUNT_REG);
70 		available_words &= RNG_FIFO_COUNT_MASK;
71 
72 		if (available_words != 0) {
73 			available_words = MIN(available_words,
74 					*words_read - word_processed);
75 
76 			for (i = 0; i < available_words; i++)
77 				p_out[word_processed + i] =
78 					mmio_read_32(RNG_FIFO_DATA_REG);
79 			word_processed += available_words;
80 		} else {
81 			udelay(50);
82 		}
83 
84 		if (word_processed == *words_read)
85 			break;
86 
87 	} while (--wait_count);
88 
89 	if (word_processed != *words_read) {
90 		ERROR("RNG Timeout: requested %d word(s) got %d\n",
91 				*words_read, word_processed);
92 		*words_read = word_processed;
93 		return -1;
94 	}
95 
96 	return 0;
97 }
98