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