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