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