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