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 TEE_Result hw_get_random_bytes(void *buf, size_t len) 66 { 67 uint8_t *rngbuf = buf; 68 uint32_t val = 0; 69 size_t len_to_copy = 0; 70 71 assert(buf); 72 assert(xiphera_trng_base); 73 74 while (len) { 75 uint32_t exceptions = cpu_spin_lock_xsave(&trng_lock); 76 77 if (xiphera_trng_random_available()) { 78 val = xiphera_trng_read32(); 79 80 len_to_copy = MIN(len, sizeof(uint32_t)); 81 memcpy(rngbuf, &val, len_to_copy); 82 rngbuf += len_to_copy; 83 len -= len_to_copy; 84 } 85 86 cpu_spin_unlock_xrestore(&trng_lock, exceptions); 87 } 88 89 return TEE_SUCCESS; 90 } 91 92 static TEE_Result xiphera_trng_probe(const void *fdt, int node, 93 const void *compat_data __unused) 94 { 95 int dt_status = fdt_get_status(fdt, node); 96 uint32_t status = 0; 97 size_t size = 0; 98 99 /* Skip non-secure instances */ 100 if (dt_status != DT_STATUS_OK_SEC) 101 return TEE_ERROR_NODE_DISABLED; 102 103 if (xiphera_trng_base) { 104 EMSG("Only one secure instance is supported"); 105 return TEE_ERROR_GENERIC; 106 } 107 108 if (dt_map_dev(fdt, node, &xiphera_trng_base, &size, DT_MAP_AUTO) < 0) 109 return TEE_ERROR_GENERIC; 110 111 /* 112 * The TRNG needs to be first reset in order to provide stable 113 * operation. 114 * 115 * Reset of the chip should complete within 200 us but in some cases it 116 * could take up to 400 us. If it is not ready within 400 us assume 117 * there is problem. 118 */ 119 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_RESET); 120 udelay(200); 121 122 status = io_read32(xiphera_trng_base + STATUS_REG); 123 if (status != TRNG_ACK_RESET) { 124 /* 125 * Give it additional 200 us to allow it to reset. 126 * 127 * If still not done -> error out. 128 */ 129 udelay(200); 130 status = io_read32(xiphera_trng_base + STATUS_REG); 131 if (status != TRNG_ACK_RESET) { 132 EMSG("Failed to reset TRNG"); 133 return TEE_ERROR_GENERIC; 134 } 135 } 136 137 /* 138 * Now TRNG should be internally stable. 139 * 140 * Clear internal random number generation engine to start in stable 141 * state and give it 20 ms to enable good random number entropy and 142 * then check that random number engine is ready. 143 */ 144 io_write32(xiphera_trng_base + CONTROL_REG, 145 HOST_TO_TRNG_RELEASE_RESET); 146 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ENABLE); 147 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ZEROIZE); 148 mdelay(20); 149 150 status = io_read32(xiphera_trng_base + STATUS_REG); 151 if (status != TRNG_SUCCESSFUL_STARTUP) { 152 /* 153 * Check specifically if there were startup test errors to aid 154 * in debugging TRNG implementation in FPGA 155 */ 156 if (status == TRNG_FAILED_STARTUP) { 157 EMSG("Startup tests have failed"); 158 return TEE_ERROR_GENERIC; 159 } 160 161 EMSG("Startup tests yielded no response -> TRNG stuck"); 162 return TEE_ERROR_GENERIC; 163 } 164 165 io_write32(xiphera_trng_base + CONTROL_REG, HOST_TO_TRNG_ACK_ZEROIZE); 166 167 DMSG("TRNG initialized"); 168 169 return TEE_SUCCESS; 170 } 171 172 static const struct dt_device_match xiphera_trng_match_table[] = { 173 { .compatible = "xiphera,xip8001b-trng" }, 174 { } 175 }; 176 177 DEFINE_DT_DRIVER(xiphera_trng_dt_driver) = { 178 .name = "xiphera_trng", 179 .type = DT_DRIVER_NOTYPE, 180 .match_table = xiphera_trng_match_table, 181 .probe = xiphera_trng_probe, 182 }; 183