blob: 75fda00a915a882e0360bc0156c1cb0ad8744798 [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/*
* Copyright 2019 Broadcom.
*/
#include <drivers/bcm_hwrng.h>
#include <initcall.h>
#include <io.h>
#include <kernel/delay.h>
#include <mm/core_memprot.h>
#include <platform_config.h>
#include <trace.h>
/* Registers */
#define RNG_CTRL_OFFSET 0x00
#define RNG_CTRL_MASK 0x00001fff
#define RNG_CTRL_DISABLE 0x00000000
#define RNG_CTRL_ENABLE 0x00000001
#define RNG_SOFT_RESET_OFFSET 0x04
#define RNG_SOFT_RESET_MASK 0x00000001
#define RNG_FIFO_DATA_OFFSET 0x20
#define RNG_FIFO_COUNT_OFFSET 0x24
#define RNG_FIFO_COUNT_MASK 0x000000ff
#define RNG_TIMEOUT_US 10000
static vaddr_t bcm_hwrng_base;
static void bcm_hwrng_reset(void)
{
/* Disable RBG */
io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET,
RNG_CTRL_MASK, RNG_CTRL_DISABLE);
/* Reset RNG and RBG */
io_setbits32(bcm_hwrng_base +
RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK);
io_clrbits32(bcm_hwrng_base +
RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK);
/* Enable RBG */
io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET,
RNG_CTRL_MASK, RNG_CTRL_ENABLE);
}
uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read)
{
uint32_t available_words = 0;
uint32_t num_words = 0;
uint32_t i = 0;
uint64_t timeout = timeout_init_us(RNG_TIMEOUT_US);
assert(bcm_hwrng_base);
do {
available_words = io_read32(bcm_hwrng_base +
RNG_FIFO_COUNT_OFFSET);
available_words = available_words & RNG_FIFO_COUNT_MASK;
} while (!available_words && !timeout_elapsed(timeout));
if ((available_words > 0) && (words_to_read > 0)) {
num_words = MIN(available_words, words_to_read);
for (i = 0; i < num_words; i++)
p_out[i] = io_read32(bcm_hwrng_base +
RNG_FIFO_DATA_OFFSET);
}
return num_words;
}
static TEE_Result bcm_hwrng_init(void)
{
bcm_hwrng_base = (vaddr_t)phys_to_virt(HWRNG_BASE, MEM_AREA_IO_SEC);
bcm_hwrng_reset();
DMSG("bcm_hwrng init done\n");
return TEE_SUCCESS;
}
driver_init(bcm_hwrng_init);