xref: /optee_os/core/drivers/bcm_hwrng.c (revision 16b6c0f6066f4b4036581bc7bd04508251a5bfb0)
1*16b6c0f6SSandeep Tripathy // SPDX-License-Identifier: BSD-2-Clause
2*16b6c0f6SSandeep Tripathy /*
3*16b6c0f6SSandeep Tripathy  * Copyright 2019 Broadcom.
4*16b6c0f6SSandeep Tripathy  */
5*16b6c0f6SSandeep Tripathy 
6*16b6c0f6SSandeep Tripathy #include <drivers/bcm_hwrng.h>
7*16b6c0f6SSandeep Tripathy #include <initcall.h>
8*16b6c0f6SSandeep Tripathy #include <io.h>
9*16b6c0f6SSandeep Tripathy #include <kernel/delay.h>
10*16b6c0f6SSandeep Tripathy #include <mm/core_memprot.h>
11*16b6c0f6SSandeep Tripathy #include <platform_config.h>
12*16b6c0f6SSandeep Tripathy #include <trace.h>
13*16b6c0f6SSandeep Tripathy 
14*16b6c0f6SSandeep Tripathy /* Registers */
15*16b6c0f6SSandeep Tripathy #define RNG_CTRL_OFFSET         0x00
16*16b6c0f6SSandeep Tripathy #define RNG_CTRL_MASK           0x00001fff
17*16b6c0f6SSandeep Tripathy #define RNG_CTRL_DISABLE        0x00000000
18*16b6c0f6SSandeep Tripathy #define RNG_CTRL_ENABLE         0x00000001
19*16b6c0f6SSandeep Tripathy 
20*16b6c0f6SSandeep Tripathy #define RNG_SOFT_RESET_OFFSET   0x04
21*16b6c0f6SSandeep Tripathy #define RNG_SOFT_RESET_MASK     0x00000001
22*16b6c0f6SSandeep Tripathy 
23*16b6c0f6SSandeep Tripathy #define RNG_FIFO_DATA_OFFSET    0x20
24*16b6c0f6SSandeep Tripathy 
25*16b6c0f6SSandeep Tripathy #define RNG_FIFO_COUNT_OFFSET   0x24
26*16b6c0f6SSandeep Tripathy 
27*16b6c0f6SSandeep Tripathy #define RNG_FIFO_COUNT_MASK     0x000000ff
28*16b6c0f6SSandeep Tripathy #define RNG_TIMEOUT_US		10000
29*16b6c0f6SSandeep Tripathy 
30*16b6c0f6SSandeep Tripathy static vaddr_t bcm_hwrng_base;
31*16b6c0f6SSandeep Tripathy 
32*16b6c0f6SSandeep Tripathy static void bcm_hwrng_reset(void)
33*16b6c0f6SSandeep Tripathy {
34*16b6c0f6SSandeep Tripathy 	/* Disable RBG */
35*16b6c0f6SSandeep Tripathy 	io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET,
36*16b6c0f6SSandeep Tripathy 			RNG_CTRL_MASK, RNG_CTRL_DISABLE);
37*16b6c0f6SSandeep Tripathy 	/* Reset RNG and RBG */
38*16b6c0f6SSandeep Tripathy 	io_setbits32(bcm_hwrng_base +
39*16b6c0f6SSandeep Tripathy 		     RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK);
40*16b6c0f6SSandeep Tripathy 	io_clrbits32(bcm_hwrng_base +
41*16b6c0f6SSandeep Tripathy 		     RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK);
42*16b6c0f6SSandeep Tripathy 	/* Enable RBG */
43*16b6c0f6SSandeep Tripathy 	io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET,
44*16b6c0f6SSandeep Tripathy 			RNG_CTRL_MASK, RNG_CTRL_ENABLE);
45*16b6c0f6SSandeep Tripathy }
46*16b6c0f6SSandeep Tripathy 
47*16b6c0f6SSandeep Tripathy uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read)
48*16b6c0f6SSandeep Tripathy {
49*16b6c0f6SSandeep Tripathy 	uint32_t available_words = 0;
50*16b6c0f6SSandeep Tripathy 	uint32_t num_words = 0;
51*16b6c0f6SSandeep Tripathy 	uint32_t i = 0;
52*16b6c0f6SSandeep Tripathy 	uint64_t timeout = timeout_init_us(RNG_TIMEOUT_US);
53*16b6c0f6SSandeep Tripathy 
54*16b6c0f6SSandeep Tripathy 	assert(bcm_hwrng_base);
55*16b6c0f6SSandeep Tripathy 
56*16b6c0f6SSandeep Tripathy 	do {
57*16b6c0f6SSandeep Tripathy 		available_words = io_read32(bcm_hwrng_base +
58*16b6c0f6SSandeep Tripathy 					    RNG_FIFO_COUNT_OFFSET);
59*16b6c0f6SSandeep Tripathy 		available_words = available_words & RNG_FIFO_COUNT_MASK;
60*16b6c0f6SSandeep Tripathy 	} while (!available_words && !timeout_elapsed(timeout));
61*16b6c0f6SSandeep Tripathy 
62*16b6c0f6SSandeep Tripathy 	if ((available_words > 0) && (words_to_read > 0)) {
63*16b6c0f6SSandeep Tripathy 		num_words =  MIN(available_words, words_to_read);
64*16b6c0f6SSandeep Tripathy 		for (i = 0; i < num_words; i++)
65*16b6c0f6SSandeep Tripathy 			p_out[i] = io_read32(bcm_hwrng_base +
66*16b6c0f6SSandeep Tripathy 					     RNG_FIFO_DATA_OFFSET);
67*16b6c0f6SSandeep Tripathy 	}
68*16b6c0f6SSandeep Tripathy 
69*16b6c0f6SSandeep Tripathy 	return num_words;
70*16b6c0f6SSandeep Tripathy }
71*16b6c0f6SSandeep Tripathy 
72*16b6c0f6SSandeep Tripathy static TEE_Result bcm_hwrng_init(void)
73*16b6c0f6SSandeep Tripathy {
74*16b6c0f6SSandeep Tripathy 	bcm_hwrng_base = (vaddr_t)phys_to_virt(HWRNG_BASE, MEM_AREA_IO_SEC);
75*16b6c0f6SSandeep Tripathy 
76*16b6c0f6SSandeep Tripathy 	bcm_hwrng_reset();
77*16b6c0f6SSandeep Tripathy 
78*16b6c0f6SSandeep Tripathy 	DMSG("bcm_hwrng init done\n");
79*16b6c0f6SSandeep Tripathy 	return TEE_SUCCESS;
80*16b6c0f6SSandeep Tripathy }
81*16b6c0f6SSandeep Tripathy 
82*16b6c0f6SSandeep Tripathy driver_init(bcm_hwrng_init);
83