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