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 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 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 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"); 80 return TEE_SUCCESS; 81 } 82 83 driver_init(bcm_hwrng_init); 84