diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 17:43:51 +0000 |
commit | be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b (patch) | |
tree | 779c248fb61c83f65d1f0dc867f2053d76b4e03a /drivers/brcm/rng.c | |
parent | Initial commit. (diff) | |
download | arm-trusted-firmware-be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b.tar.xz arm-trusted-firmware-be58c81aff4cd4c0ccf43dbd7998da4a6a08c03b.zip |
Adding upstream version 2.10.0+dfsg.upstream/2.10.0+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'drivers/brcm/rng.c')
-rw-r--r-- | drivers/brcm/rng.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/brcm/rng.c b/drivers/brcm/rng.c new file mode 100644 index 0000000..ee2e656 --- /dev/null +++ b/drivers/brcm/rng.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <drivers/delay_timer.h> +#include <lib/mmio.h> +#include <platform_def.h> + +#define RNG_CTRL_REG (RNG_BASE_ADDR + 0x00) +#define RNG_CTRL_MASK 0x00001FFF +#define RNG_CTRL_ENABLE 0x00000001 +#define RNG_CTRL_DISABLE 0x00000000 + +#define RNG_SOFT_RESET_REG (RNG_BASE_ADDR + 0x04) +#define RNG_SOFT_RESET_MASK 0x00000001 + +#define RNG_FIFO_DATA_REG (RNG_BASE_ADDR + 0x20) + +#define RNG_FIFO_COUNT_REG (RNG_BASE_ADDR + 0x24) +#define RNG_FIFO_COUNT_MASK 0x000000FF + +#define RNG_FIFO_WORDS_MAX 16 +#define MAX_WAIT_COUNT_50US 20000 + + +static void rng_reset(void) +{ + /* Disable RBG */ + mmio_clrbits_32(RNG_CTRL_REG, RNG_CTRL_MASK); + + /* Reset RNG and RBG */ + mmio_setbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK); + + /* Take all out of reset */ + mmio_clrbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK); +} + +static void rng_enable(void) +{ + /* Setup RNG. */ + mmio_clrsetbits_32(RNG_CTRL_REG, RNG_CTRL_MASK, RNG_CTRL_ENABLE); +} + +int rng_init(void) +{ + rng_reset(); + + rng_enable(); + + return 0; +} + +int rng_read(uint32_t *p_out, uint32_t *words_read) +{ + uint32_t available_words; + uint32_t i; + uint32_t word_processed = 0; + uint32_t wait_count = MAX_WAIT_COUNT_50US; + + if (*words_read == 0) { + ERROR("RNG Parameter: No word requested\n"); + return -1; + } + + do { + available_words = mmio_read_32(RNG_FIFO_COUNT_REG); + available_words &= RNG_FIFO_COUNT_MASK; + + if (available_words != 0) { + available_words = MIN(available_words, + *words_read - word_processed); + + for (i = 0; i < available_words; i++) + p_out[word_processed + i] = + mmio_read_32(RNG_FIFO_DATA_REG); + word_processed += available_words; + } else { + udelay(50); + } + + if (word_processed == *words_read) + break; + + } while (--wait_count); + + if (word_processed != *words_read) { + ERROR("RNG Timeout: requested %d word(s) got %d\n", + *words_read, word_processed); + *words_read = word_processed; + return -1; + } + + return 0; +} |