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