1*8c1740e2SSuyuan Su /* 2*8c1740e2SSuyuan Su * Copyright (c) 2024, MediaTek Inc. All rights reserved. 3*8c1740e2SSuyuan Su * 4*8c1740e2SSuyuan Su * SPDX-License-Identifier: BSD-3-Clause 5*8c1740e2SSuyuan Su */ 6*8c1740e2SSuyuan Su 7*8c1740e2SSuyuan Su #include <assert.h> 8*8c1740e2SSuyuan Su #include <errno.h> 9*8c1740e2SSuyuan Su #include <stdint.h> 10*8c1740e2SSuyuan Su 11*8c1740e2SSuyuan Su #include <common/debug.h> 12*8c1740e2SSuyuan Su #include <drivers/delay_timer.h> 13*8c1740e2SSuyuan Su #include <lib/mmio.h> 14*8c1740e2SSuyuan Su #include <lib/smccc.h> 15*8c1740e2SSuyuan Su #include <lib/spinlock.h> 16*8c1740e2SSuyuan Su #include <plat/common/platform.h> 17*8c1740e2SSuyuan Su #include <platform_def.h> 18*8c1740e2SSuyuan Su #include <services/trng_svc.h> 19*8c1740e2SSuyuan Su #include <smccc_helpers.h> 20*8c1740e2SSuyuan Su 21*8c1740e2SSuyuan Su #include <mtk_mmap_pool.h> 22*8c1740e2SSuyuan Su #include <mtk_sip_svc.h> 23*8c1740e2SSuyuan Su #include "rng_plat.h" 24*8c1740e2SSuyuan Su 25*8c1740e2SSuyuan Su static spinlock_t rng_lock; 26*8c1740e2SSuyuan Su 27*8c1740e2SSuyuan Su static int trng_wait(uint32_t reg, uint32_t expected_value) 28*8c1740e2SSuyuan Su { 29*8c1740e2SSuyuan Su uint64_t timeout = timeout_init_us(TRNG_TIME_OUT); 30*8c1740e2SSuyuan Su uint32_t value = 0; 31*8c1740e2SSuyuan Su 32*8c1740e2SSuyuan Su do { 33*8c1740e2SSuyuan Su value = mmio_read_32(reg); 34*8c1740e2SSuyuan Su if ((value & expected_value) == expected_value) 35*8c1740e2SSuyuan Su return 0; 36*8c1740e2SSuyuan Su 37*8c1740e2SSuyuan Su udelay(10); 38*8c1740e2SSuyuan Su } while (!timeout_elapsed(timeout)); 39*8c1740e2SSuyuan Su 40*8c1740e2SSuyuan Su return -ETIMEDOUT; 41*8c1740e2SSuyuan Su } 42*8c1740e2SSuyuan Su 43*8c1740e2SSuyuan Su static int trng_write(uint32_t reg, uint32_t value, 44*8c1740e2SSuyuan Su uint32_t read_reg, uint32_t expected_value) 45*8c1740e2SSuyuan Su { 46*8c1740e2SSuyuan Su int retry = MTK_TRNG_MAX_ROUND; 47*8c1740e2SSuyuan Su uint32_t read_value = 0; 48*8c1740e2SSuyuan Su 49*8c1740e2SSuyuan Su do { 50*8c1740e2SSuyuan Su mmio_write_32(reg, value); 51*8c1740e2SSuyuan Su 52*8c1740e2SSuyuan Su read_value = mmio_read_32(read_reg); 53*8c1740e2SSuyuan Su if ((read_value & value) == expected_value) 54*8c1740e2SSuyuan Su return 0; 55*8c1740e2SSuyuan Su 56*8c1740e2SSuyuan Su udelay(10); 57*8c1740e2SSuyuan Su } while (--retry > 0); 58*8c1740e2SSuyuan Su 59*8c1740e2SSuyuan Su return -ETIMEDOUT; 60*8c1740e2SSuyuan Su } 61*8c1740e2SSuyuan Su 62*8c1740e2SSuyuan Su static uint32_t trng_prng(uint32_t *rand) 63*8c1740e2SSuyuan Su { 64*8c1740e2SSuyuan Su int32_t ret = 0; 65*8c1740e2SSuyuan Su uint32_t seed[4] = {0}; 66*8c1740e2SSuyuan Su 67*8c1740e2SSuyuan Su if (rand == NULL) 68*8c1740e2SSuyuan Su return MTK_SIP_E_INVALID_PARAM; 69*8c1740e2SSuyuan Su 70*8c1740e2SSuyuan Su /* ungate */ 71*8c1740e2SSuyuan Su ret = trng_write(TRNG_PDN_CLR, TRNG_PDN_VALUE, TRNG_PDN_STATUS, 0); 72*8c1740e2SSuyuan Su if (ret) { 73*8c1740e2SSuyuan Su ERROR("%s: ungate fail\n", __func__); 74*8c1740e2SSuyuan Su return MTK_SIP_E_NOT_SUPPORTED; 75*8c1740e2SSuyuan Su } 76*8c1740e2SSuyuan Su 77*8c1740e2SSuyuan Su /* read random data once and drop it */ 78*8c1740e2SSuyuan Su seed[0] = mmio_read_32(TRNG_DATA); 79*8c1740e2SSuyuan Su 80*8c1740e2SSuyuan Su /* enable von-neumann extractor */ 81*8c1740e2SSuyuan Su mmio_setbits_32(TRNG_CONF, TRNG_CONF_VON_EN); 82*8c1740e2SSuyuan Su 83*8c1740e2SSuyuan Su /* start */ 84*8c1740e2SSuyuan Su mmio_setbits_32(TRNG_CTRL, TRNG_CTRL_START); 85*8c1740e2SSuyuan Su 86*8c1740e2SSuyuan Su /* get seeds from trng */ 87*8c1740e2SSuyuan Su for (int i = 0; i < ARRAY_SIZE(seed); i++) { 88*8c1740e2SSuyuan Su ret = trng_wait(TRNG_CTRL, TRNG_CTRL_RDY); 89*8c1740e2SSuyuan Su if (ret) { 90*8c1740e2SSuyuan Su ERROR("%s: trng NOT ready\n", __func__); 91*8c1740e2SSuyuan Su return MTK_SIP_E_NOT_SUPPORTED; 92*8c1740e2SSuyuan Su } 93*8c1740e2SSuyuan Su 94*8c1740e2SSuyuan Su seed[i] = mmio_read_32(TRNG_DATA); 95*8c1740e2SSuyuan Su } 96*8c1740e2SSuyuan Su 97*8c1740e2SSuyuan Su /* stop */ 98*8c1740e2SSuyuan Su mmio_clrbits_32(TRNG_CTRL, TRNG_CTRL_START); 99*8c1740e2SSuyuan Su 100*8c1740e2SSuyuan Su /* gate */ 101*8c1740e2SSuyuan Su ret = trng_write(TRNG_PDN_SET, TRNG_PDN_VALUE, TRNG_PDN_STATUS, TRNG_PDN_VALUE); 102*8c1740e2SSuyuan Su if (ret) { 103*8c1740e2SSuyuan Su ERROR("%s: gate fail\n", __func__); 104*8c1740e2SSuyuan Su return MTK_SIP_E_NOT_SUPPORTED; 105*8c1740e2SSuyuan Su } 106*8c1740e2SSuyuan Su 107*8c1740e2SSuyuan Su for (int i = 0; i < ARRAY_SIZE(seed); i++) 108*8c1740e2SSuyuan Su rand[i] = seed[i]; 109*8c1740e2SSuyuan Su 110*8c1740e2SSuyuan Su return 0; 111*8c1740e2SSuyuan Su } 112*8c1740e2SSuyuan Su 113*8c1740e2SSuyuan Su static uint32_t get_true_rnd(uint32_t *val, uint32_t num) 114*8c1740e2SSuyuan Su { 115*8c1740e2SSuyuan Su uint32_t rand[4] = {0}; 116*8c1740e2SSuyuan Su uint32_t ret; 117*8c1740e2SSuyuan Su 118*8c1740e2SSuyuan Su if (val == NULL || num > ARRAY_SIZE(rand)) 119*8c1740e2SSuyuan Su return MTK_SIP_E_INVALID_PARAM; 120*8c1740e2SSuyuan Su 121*8c1740e2SSuyuan Su spin_lock(&rng_lock); 122*8c1740e2SSuyuan Su ret = trng_prng(rand); 123*8c1740e2SSuyuan Su spin_unlock(&rng_lock); 124*8c1740e2SSuyuan Su 125*8c1740e2SSuyuan Su for (int i = 0; i < num; i++) 126*8c1740e2SSuyuan Su val[i] = rand[i]; 127*8c1740e2SSuyuan Su 128*8c1740e2SSuyuan Su return ret; 129*8c1740e2SSuyuan Su } 130*8c1740e2SSuyuan Su 131*8c1740e2SSuyuan Su /* 132*8c1740e2SSuyuan Su * plat_get_entropy - get 64-bit random number data which is used form 133*8c1740e2SSuyuan Su * atf early stage 134*8c1740e2SSuyuan Su * output - out: output 64-bit entropy combine with 2 32-bit random number 135*8c1740e2SSuyuan Su */ 136*8c1740e2SSuyuan Su bool plat_get_entropy(uint64_t *out) 137*8c1740e2SSuyuan Su { 138*8c1740e2SSuyuan Su uint32_t entropy_pool[2] = {0}; 139*8c1740e2SSuyuan Su uint32_t ret; 140*8c1740e2SSuyuan Su 141*8c1740e2SSuyuan Su assert(out); 142*8c1740e2SSuyuan Su assert(!check_uptr_overflow((uintptr_t)out, sizeof(*out))); 143*8c1740e2SSuyuan Su 144*8c1740e2SSuyuan Su /* Get 2 32-bits entropy */ 145*8c1740e2SSuyuan Su ret = get_true_rnd(entropy_pool, ARRAY_SIZE(entropy_pool)); 146*8c1740e2SSuyuan Su if (ret) 147*8c1740e2SSuyuan Su return false; 148*8c1740e2SSuyuan Su 149*8c1740e2SSuyuan Su /* Output 8 bytes entropy combine with 2 32-bit random number. */ 150*8c1740e2SSuyuan Su *out = ((uint64_t)entropy_pool[0] << 32) | entropy_pool[1]; 151*8c1740e2SSuyuan Su 152*8c1740e2SSuyuan Su return true; 153*8c1740e2SSuyuan Su } 154