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