xref: /optee_os/core/drivers/bcm_hwrng.c (revision bce2f88ab347b28f4149dacef2ad48ac67a500b6)
116b6c0f6SSandeep Tripathy // SPDX-License-Identifier: BSD-2-Clause
216b6c0f6SSandeep Tripathy /*
316b6c0f6SSandeep Tripathy  * Copyright 2019 Broadcom.
416b6c0f6SSandeep Tripathy  */
516b6c0f6SSandeep Tripathy 
616b6c0f6SSandeep Tripathy #include <drivers/bcm_hwrng.h>
716b6c0f6SSandeep Tripathy #include <initcall.h>
816b6c0f6SSandeep Tripathy #include <io.h>
916b6c0f6SSandeep Tripathy #include <kernel/delay.h>
1016b6c0f6SSandeep Tripathy #include <mm/core_memprot.h>
1116b6c0f6SSandeep Tripathy #include <platform_config.h>
1216b6c0f6SSandeep Tripathy #include <trace.h>
1316b6c0f6SSandeep Tripathy 
1416b6c0f6SSandeep Tripathy /* Registers */
1516b6c0f6SSandeep Tripathy #define RNG_CTRL_OFFSET         0x00
1616b6c0f6SSandeep Tripathy #define RNG_CTRL_MASK           0x00001fff
1716b6c0f6SSandeep Tripathy #define RNG_CTRL_DISABLE        0x00000000
1816b6c0f6SSandeep Tripathy #define RNG_CTRL_ENABLE         0x00000001
1916b6c0f6SSandeep Tripathy 
2016b6c0f6SSandeep Tripathy #define RNG_SOFT_RESET_OFFSET   0x04
2116b6c0f6SSandeep Tripathy #define RNG_SOFT_RESET_MASK     0x00000001
2216b6c0f6SSandeep Tripathy 
2316b6c0f6SSandeep Tripathy #define RNG_FIFO_DATA_OFFSET    0x20
2416b6c0f6SSandeep Tripathy 
2516b6c0f6SSandeep Tripathy #define RNG_FIFO_COUNT_OFFSET   0x24
2616b6c0f6SSandeep Tripathy 
2716b6c0f6SSandeep Tripathy #define RNG_FIFO_COUNT_MASK     0x000000ff
2816b6c0f6SSandeep Tripathy #define RNG_TIMEOUT_US		10000
2916b6c0f6SSandeep Tripathy 
3016b6c0f6SSandeep Tripathy static vaddr_t bcm_hwrng_base;
3116b6c0f6SSandeep Tripathy 
bcm_hwrng_reset(void)3216b6c0f6SSandeep Tripathy static void bcm_hwrng_reset(void)
3316b6c0f6SSandeep Tripathy {
3416b6c0f6SSandeep Tripathy 	/* Disable RBG */
3516b6c0f6SSandeep Tripathy 	io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET,
3616b6c0f6SSandeep Tripathy 			RNG_CTRL_MASK, RNG_CTRL_DISABLE);
3716b6c0f6SSandeep Tripathy 	/* Reset RNG and RBG */
3816b6c0f6SSandeep Tripathy 	io_setbits32(bcm_hwrng_base +
3916b6c0f6SSandeep Tripathy 		     RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK);
4016b6c0f6SSandeep Tripathy 	io_clrbits32(bcm_hwrng_base +
4116b6c0f6SSandeep Tripathy 		     RNG_SOFT_RESET_OFFSET, RNG_SOFT_RESET_MASK);
4216b6c0f6SSandeep Tripathy 	/* Enable RBG */
4316b6c0f6SSandeep Tripathy 	io_clrsetbits32(bcm_hwrng_base + RNG_CTRL_OFFSET,
4416b6c0f6SSandeep Tripathy 			RNG_CTRL_MASK, RNG_CTRL_ENABLE);
4516b6c0f6SSandeep Tripathy }
4616b6c0f6SSandeep Tripathy 
bcm_hwrng_read_rng(uint32_t * p_out,uint32_t words_to_read)4716b6c0f6SSandeep Tripathy uint32_t bcm_hwrng_read_rng(uint32_t *p_out, uint32_t words_to_read)
4816b6c0f6SSandeep Tripathy {
4916b6c0f6SSandeep Tripathy 	uint32_t available_words = 0;
5016b6c0f6SSandeep Tripathy 	uint32_t num_words = 0;
5116b6c0f6SSandeep Tripathy 	uint32_t i = 0;
5216b6c0f6SSandeep Tripathy 	uint64_t timeout = timeout_init_us(RNG_TIMEOUT_US);
5316b6c0f6SSandeep Tripathy 
5416b6c0f6SSandeep Tripathy 	assert(bcm_hwrng_base);
5516b6c0f6SSandeep Tripathy 
5616b6c0f6SSandeep Tripathy 	do {
5716b6c0f6SSandeep Tripathy 		available_words = io_read32(bcm_hwrng_base +
5816b6c0f6SSandeep Tripathy 					    RNG_FIFO_COUNT_OFFSET);
5916b6c0f6SSandeep Tripathy 		available_words = available_words & RNG_FIFO_COUNT_MASK;
6016b6c0f6SSandeep Tripathy 	} while (!available_words && !timeout_elapsed(timeout));
6116b6c0f6SSandeep Tripathy 
6216b6c0f6SSandeep Tripathy 	if ((available_words > 0) && (words_to_read > 0)) {
6316b6c0f6SSandeep Tripathy 		num_words =  MIN(available_words, words_to_read);
6416b6c0f6SSandeep Tripathy 		for (i = 0; i < num_words; i++)
6516b6c0f6SSandeep Tripathy 			p_out[i] = io_read32(bcm_hwrng_base +
6616b6c0f6SSandeep Tripathy 					     RNG_FIFO_DATA_OFFSET);
6716b6c0f6SSandeep Tripathy 	}
6816b6c0f6SSandeep Tripathy 
6916b6c0f6SSandeep Tripathy 	return num_words;
7016b6c0f6SSandeep Tripathy }
7116b6c0f6SSandeep Tripathy 
bcm_hwrng_init(void)7216b6c0f6SSandeep Tripathy static TEE_Result bcm_hwrng_init(void)
7316b6c0f6SSandeep Tripathy {
74c2e4eb43SAnton Rybakov 	bcm_hwrng_base = (vaddr_t)phys_to_virt(HWRNG_BASE, MEM_AREA_IO_SEC,
75c2e4eb43SAnton Rybakov 					       HWRNG_END - HWRNG_BASE);
7616b6c0f6SSandeep Tripathy 
7716b6c0f6SSandeep Tripathy 	bcm_hwrng_reset();
7816b6c0f6SSandeep Tripathy 
79*bce2f88aSVincent Mailhol 	DMSG("bcm_hwrng init done");
8016b6c0f6SSandeep Tripathy 	return TEE_SUCCESS;
8116b6c0f6SSandeep Tripathy }
8216b6c0f6SSandeep Tripathy 
8316b6c0f6SSandeep Tripathy driver_init(bcm_hwrng_init);
84