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