1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2022, Vaisala Oyj 4 */ 5 6 #include <assert.h> 7 #include <io.h> 8 #include <kernel/boot.h> 9 #include <kernel/delay.h> 10 #include <kernel/dt.h> 11 #include <kernel/dt_driver.h> 12 #include <kernel/spinlock.h> 13 #include <libfdt.h> 14 #include <platform_config.h> 15 #include <rng_support.h> 16 #include <string.h> 17 #include <tee/tee_cryp_utl.h> 18 19 #define CONTROL_REG 0x00000000 20 #define STATUS_REG 0x00000004 21 #define RAND_REG 0x00000000 22 23 #define HOST_TO_TRNG_RESET 0x00000001 24 #define HOST_TO_TRNG_RELEASE_RESET 0x00000002 25 #define HOST_TO_TRNG_ENABLE 0x80000000 26 #define HOST_TO_TRNG_ZEROIZE 0x80000004 27 #define HOST_TO_TRNG_ACK_ZEROIZE 0x80000008 28 #define HOST_TO_TRNG_READ 0x8000000F 29 30 /* trng statuses */ 31 #define TRNG_ACK_RESET 0x000000AC 32 #define TRNG_SUCCESSFUL_STARTUP 0x00000057 33 #define TRNG_FAILED_STARTUP 0x000000FA 34 #define TRNG_NEW_RAND_AVAILABLE 0x000000ED 35 36 static unsigned int trng_lock = SPINLOCK_UNLOCK; 37 38 static vaddr_t xiphera_trng_base; 39 40 static bool xiphera_trng_random_available(void) 41 { 42 uint32_t status = 0; 43 44 status = io_read32(xiphera_trng_base + STATUS_REG); 45 46 return status == TRNG_NEW_RAND_AVAILABLE; 47 } 48 49 static uint32_t xiphera_trng_read32(void) 50 { 51 uint32_t value = 0; 52 53 value = io_read32(xiphera_trng_base + RAND_REG); 54 55 /* 56 * Ack that RNG value has been consumed and trigger new one to be 57 * generated 58 */ 59 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_READ); 60 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE); 61 62 return value; 63 } 64 65 /* This is a true RNG, no need for seeding */ 66 void plat_rng_init(void) 67 { 68 } 69 70 TEE_Result hw_get_random_bytes(void *buf, size_t len) 71 { 72 uint8_t *rngbuf = buf; 73 uint32_t val = 0; 74 size_t len_to_copy = 0; 75 76 assert(buf); 77 assert(xiphera_trng_base); 78 79 while (len) { 80 uint32_t exceptions = cpu_spin_lock_xsave(&trng_lock); 81 82 if (xiphera_trng_random_available()) { 83 val = xiphera_trng_read32(); 84 85 len_to_copy = MIN(len, sizeof(uint32_t)); 86 memcpy(rngbuf, &val, len_to_copy); 87 rngbuf += len_to_copy; 88 len -= len_to_copy; 89 } 90 91 cpu_spin_unlock_xrestore(&trng_lock, exceptions); 92 } 93 94 return TEE_SUCCESS; 95 } 96 97 static TEE_Result xiphera_trng_probe(const void *fdt, int node, 98 const void *compat_data __unused) 99 { 100 int dt_status = fdt_get_status(fdt, node); 101 uint32_t status = 0; 102 size_t size = 0; 103 104 /* Skip non-secure instances */ 105 if (dt_status != DT_STATUS_OK_SEC) 106 return TEE_ERROR_NODE_DISABLED; 107 108 if (xiphera_trng_base) { 109 EMSG("Only one secure instance is supported"); 110 return TEE_ERROR_GENERIC; 111 } 112 113 if (dt_map_dev(fdt, node, &xiphera_trng_base, &size, DT_MAP_AUTO) < 0) 114 return TEE_ERROR_GENERIC; 115 116 /* 117 * The TRNG needs to be first reset in order to provide stable 118 * operation. 119 * 120 * Reset of the chip should complete within 200 us but in some cases it 121 * could take up to 400 us. If it is not ready within 400 us assume 122 * there is problem. 123 */ 124 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_RESET); 125 udelay(200); 126 127 status = io_read32(xiphera_trng_base + STATUS_REG); 128 if (status != TRNG_ACK_RESET) { 129 /* 130 * Give it additional 200 us to allow it to reset. 131 * 132 * If still not done -> error out. 133 */ 134 udelay(200); 135 status = io_read32(xiphera_trng_base + STATUS_REG); 136 if (status != TRNG_ACK_RESET) { 137 EMSG("Failed to reset TRNG"); 138 return TEE_ERROR_GENERIC; 139 } 140 } 141 142 /* 143 * Now TRNG should be internally stable. 144 * 145 * Clear internal random number generation engine to start in stable 146 * state and give it 20 ms to enable good random number entropy and 147 * then check that random number engine is ready. 148 */ 149 io_write32(xiphera_trng_base + CONTROL_REG, 150 HOST_TO_TRNG_RELEASE_RESET); 151 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE); 152 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ZEROIZE); 153 mdelay(20); 154 155 status = io_read32(xiphera_trng_base + STATUS_REG); 156 if (status != TRNG_SUCCESSFUL_STARTUP) { 157 /* 158 * Check specifically if there were startup test errors to aid 159 * in debugging TRNG implementation in FPGA 160 */ 161 if (status == TRNG_FAILED_STARTUP) { 162 EMSG("Startup tests have failed"); 163 return TEE_ERROR_GENERIC; 164 } 165 166 EMSG("Startup tests yielded no response -> TRNG stuck"); 167 return TEE_ERROR_GENERIC; 168 } 169 170 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE); 171 172 DMSG("TRNG initialized"); 173 174 return TEE_SUCCESS; 175 } 176 177 static const struct dt_device_match xiphera_trng_match_table[] = { 178 { .compatible = "xiphera,xip8001b-trng" }, 179 { } 180 }; 181 182 DEFINE_DT_DRIVER(xiphera_trng_dt_driver) = { 183 .name = "xiphera_trng", 184 .type = DT_DRIVER_NOTYPE, 185 .match_table = xiphera_trng_match_table, 186 .probe = xiphera_trng_probe, 187 }; 188