xref: /optee_os/core/drivers/qcom/prng/prng.c (revision ff114e13926ad6a177ec9481f4ec043671326413)
1*ff114e13SJorge Ramirez-Ortiz // SPDX-License-Identifier: BSD-3-Clause
2*ff114e13SJorge Ramirez-Ortiz /*
3*ff114e13SJorge Ramirez-Ortiz  * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
4*ff114e13SJorge Ramirez-Ortiz  */
5*ff114e13SJorge Ramirez-Ortiz 
6*ff114e13SJorge Ramirez-Ortiz #include <initcall.h>
7*ff114e13SJorge Ramirez-Ortiz #include <io.h>
8*ff114e13SJorge Ramirez-Ortiz #include <mm/core_memprot.h>
9*ff114e13SJorge Ramirez-Ortiz #include <platform_config.h>
10*ff114e13SJorge Ramirez-Ortiz #include <rng_support.h>
11*ff114e13SJorge Ramirez-Ortiz 
12*ff114e13SJorge Ramirez-Ortiz #define SEC_PRNG_REG_SIZE			0x1000
13*ff114e13SJorge Ramirez-Ortiz 
14*ff114e13SJorge Ramirez-Ortiz #define SEC_PRNG_DATA_OUT			0x0
15*ff114e13SJorge Ramirez-Ortiz #define SEC_PRNG_STATUS				0x4
16*ff114e13SJorge Ramirez-Ortiz #define SEC_PRNG_STATUS_DATA_AVAIL_BMSK		0x1
17*ff114e13SJorge Ramirez-Ortiz 
18*ff114e13SJorge Ramirez-Ortiz static struct {
19*ff114e13SJorge Ramirez-Ortiz 	paddr_t pa;
20*ff114e13SJorge Ramirez-Ortiz 	vaddr_t va;
21*ff114e13SJorge Ramirez-Ortiz } prng = {
22*ff114e13SJorge Ramirez-Ortiz 	.pa = SEC_PRNG_REG_BASE,
23*ff114e13SJorge Ramirez-Ortiz };
24*ff114e13SJorge Ramirez-Ortiz 
25*ff114e13SJorge Ramirez-Ortiz TEE_Result hw_get_random_bytes(void *buf, size_t len)
26*ff114e13SJorge Ramirez-Ortiz {
27*ff114e13SJorge Ramirez-Ortiz 	uint8_t *out = buf;
28*ff114e13SJorge Ramirez-Ortiz 	uint32_t val;
29*ff114e13SJorge Ramirez-Ortiz 
30*ff114e13SJorge Ramirez-Ortiz 	if (!prng.va)
31*ff114e13SJorge Ramirez-Ortiz 		return TEE_ERROR_NOT_SUPPORTED;
32*ff114e13SJorge Ramirez-Ortiz 
33*ff114e13SJorge Ramirez-Ortiz 	if (!out || !len)
34*ff114e13SJorge Ramirez-Ortiz 		return TEE_ERROR_BAD_PARAMETERS;
35*ff114e13SJorge Ramirez-Ortiz 
36*ff114e13SJorge Ramirez-Ortiz 	while (len) {
37*ff114e13SJorge Ramirez-Ortiz 		if (!(io_read32(prng.va + SEC_PRNG_STATUS) &
38*ff114e13SJorge Ramirez-Ortiz 		      SEC_PRNG_STATUS_DATA_AVAIL_BMSK))
39*ff114e13SJorge Ramirez-Ortiz 			continue;
40*ff114e13SJorge Ramirez-Ortiz 
41*ff114e13SJorge Ramirez-Ortiz 		while ((val = io_read32(prng.va + SEC_PRNG_DATA_OUT)) == 0)
42*ff114e13SJorge Ramirez-Ortiz 			;
43*ff114e13SJorge Ramirez-Ortiz 
44*ff114e13SJorge Ramirez-Ortiz 		for (size_t i = 0; i < sizeof(val) && len; i++) {
45*ff114e13SJorge Ramirez-Ortiz 			*out++ = (uint8_t)(val >> (i * 8));
46*ff114e13SJorge Ramirez-Ortiz 			len--;
47*ff114e13SJorge Ramirez-Ortiz 		}
48*ff114e13SJorge Ramirez-Ortiz 	}
49*ff114e13SJorge Ramirez-Ortiz 
50*ff114e13SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
51*ff114e13SJorge Ramirez-Ortiz }
52*ff114e13SJorge Ramirez-Ortiz 
53*ff114e13SJorge Ramirez-Ortiz static TEE_Result qcom_prng_init(void)
54*ff114e13SJorge Ramirez-Ortiz {
55*ff114e13SJorge Ramirez-Ortiz 	if (!core_mmu_add_mapping(MEM_AREA_IO_SEC, prng.pa, SEC_PRNG_REG_SIZE))
56*ff114e13SJorge Ramirez-Ortiz 		return TEE_ERROR_GENERIC;
57*ff114e13SJorge Ramirez-Ortiz 
58*ff114e13SJorge Ramirez-Ortiz 	prng.va = (vaddr_t)phys_to_virt_io(prng.pa, SEC_PRNG_REG_SIZE);
59*ff114e13SJorge Ramirez-Ortiz 	if (!prng.va)
60*ff114e13SJorge Ramirez-Ortiz 		return TEE_ERROR_ACCESS_DENIED;
61*ff114e13SJorge Ramirez-Ortiz 
62*ff114e13SJorge Ramirez-Ortiz 	return TEE_SUCCESS;
63*ff114e13SJorge Ramirez-Ortiz }
64*ff114e13SJorge Ramirez-Ortiz 
65*ff114e13SJorge Ramirez-Ortiz early_init(qcom_prng_init);
66