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