1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AMD Versal True Random Number Generator driver 4 * Copyright (c) 2024 - 2025 Advanced Micro Devices, Inc. 5 */ 6 7 #include <crypto/sha2.h> 8 #include <linux/bitfield.h> 9 #include <linux/clk.h> 10 #include <linux/delay.h> 11 #include <linux/firmware/xlnx-zynqmp.h> 12 #include <linux/hw_random.h> 13 #include <linux/io.h> 14 #include <linux/iopoll.h> 15 #include <linux/kernel.h> 16 #include <linux/module.h> 17 #include <linux/mod_devicetable.h> 18 #include <linux/platform_device.h> 19 20 /* TRNG Registers Offsets */ 21 #define TRNG_STATUS_OFFSET 0x4U 22 #define TRNG_CTRL_OFFSET 0x8U 23 #define TRNG_EXT_SEED_OFFSET 0x40U 24 #define TRNG_PER_STRNG_OFFSET 0x80U 25 #define TRNG_CORE_OUTPUT_OFFSET 0xC0U 26 #define TRNG_RESET_OFFSET 0xD0U 27 #define TRNG_OSC_EN_OFFSET 0xD4U 28 29 /* Mask values */ 30 #define TRNG_RESET_VAL_MASK BIT(0) 31 #define TRNG_OSC_EN_VAL_MASK BIT(0) 32 #define TRNG_CTRL_PRNGSRST_MASK BIT(0) 33 #define TRNG_CTRL_EUMODE_MASK BIT(8) 34 #define TRNG_CTRL_TRSSEN_MASK BIT(2) 35 #define TRNG_CTRL_PRNGSTART_MASK BIT(5) 36 #define TRNG_CTRL_PRNGXS_MASK BIT(3) 37 #define TRNG_CTRL_PRNGMODE_MASK BIT(7) 38 #define TRNG_STATUS_DONE_MASK BIT(0) 39 #define TRNG_STATUS_QCNT_MASK GENMASK(11, 9) 40 #define TRNG_STATUS_QCNT_16_BYTES 0x800 41 42 /* Sizes in bytes */ 43 #define TRNG_SEED_LEN_BYTES 48U 44 #define TRNG_SEC_STRENGTH_SHIFT 5U 45 #define TRNG_SEC_STRENGTH_BYTES BIT(TRNG_SEC_STRENGTH_SHIFT) 46 #define TRNG_BYTES_PER_REG 4U 47 #define TRNG_RESET_DELAY 10 48 #define TRNG_NUM_INIT_REGS 12U 49 #define TRNG_READ_4_WORD 4 50 #define TRNG_DATA_READ_DELAY 8000 51 52 struct xilinx_rng { 53 void __iomem *rng_base; 54 struct device *dev; 55 struct hwrng trng; 56 }; 57 58 static void xtrng_readwrite32(void __iomem *addr, u32 mask, u8 value) 59 { 60 u32 val; 61 62 val = ioread32(addr); 63 val = (val & (~mask)) | (mask & value); 64 iowrite32(val, addr); 65 } 66 67 static void xtrng_trng_reset(void __iomem *addr) 68 { 69 xtrng_readwrite32(addr + TRNG_RESET_OFFSET, TRNG_RESET_VAL_MASK, TRNG_RESET_VAL_MASK); 70 udelay(TRNG_RESET_DELAY); 71 xtrng_readwrite32(addr + TRNG_RESET_OFFSET, TRNG_RESET_VAL_MASK, 0); 72 } 73 74 static void xtrng_hold_reset(void __iomem *addr) 75 { 76 xtrng_readwrite32(addr + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 77 TRNG_CTRL_PRNGSRST_MASK); 78 iowrite32(TRNG_RESET_VAL_MASK, addr + TRNG_RESET_OFFSET); 79 udelay(TRNG_RESET_DELAY); 80 } 81 82 static void xtrng_softreset(struct xilinx_rng *rng) 83 { 84 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 85 TRNG_CTRL_PRNGSRST_MASK); 86 udelay(TRNG_RESET_DELAY); 87 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 0); 88 } 89 90 /* Return no. of bytes read or a negative error before any data is read. */ 91 static int xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32, bool wait) 92 { 93 int read = 0, ret; 94 int timeout = 1; 95 int i, idx; 96 u32 val; 97 98 if (wait) 99 timeout = TRNG_DATA_READ_DELAY; 100 101 for (i = 0; i < (blocks32 * 2); i++) { 102 /* TRNG core generate data in 16 bytes. Read twice to complete 32 bytes read */ 103 ret = readl_poll_timeout(rng_base + TRNG_STATUS_OFFSET, val, 104 (val & TRNG_STATUS_QCNT_MASK) == 105 TRNG_STATUS_QCNT_16_BYTES, !!wait, timeout); 106 if (ret) { 107 if (!read) 108 return ret; 109 break; 110 } 111 112 for (idx = 0; idx < TRNG_READ_4_WORD; idx++) { 113 *(buf + read) = cpu_to_be32(ioread32(rng_base + TRNG_CORE_OUTPUT_OFFSET)); 114 read += 1; 115 } 116 } 117 return read * 4; 118 } 119 120 static int xtrng_collect_random_data(struct xilinx_rng *rng, u8 *rand_gen_buf, 121 int no_of_random_bytes, bool wait) 122 { 123 u8 randbuf[TRNG_SEC_STRENGTH_BYTES]; 124 int byteleft, blocks, count = 0; 125 int full_blocks_bytes; 126 int ret; 127 128 byteleft = no_of_random_bytes & (TRNG_SEC_STRENGTH_BYTES - 1); 129 blocks = no_of_random_bytes >> TRNG_SEC_STRENGTH_SHIFT; 130 full_blocks_bytes = blocks * TRNG_SEC_STRENGTH_BYTES; 131 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, 132 TRNG_CTRL_PRNGSTART_MASK); 133 if (blocks) { 134 ret = xtrng_readblock32(rng->rng_base, (__be32 *)rand_gen_buf, blocks, wait); 135 if (ret <= 0) { 136 count = ret; 137 goto out_stop; 138 } 139 count += ret; 140 if (ret < full_blocks_bytes) 141 goto out_stop; 142 } 143 144 if (byteleft) { 145 ret = xtrng_readblock32(rng->rng_base, (__be32 *)randbuf, 1, wait); 146 if (ret < 0) { 147 if (!count) 148 count = ret; 149 goto out_stop; 150 } 151 if (!ret) 152 goto out_stop; 153 ret = min(ret, no_of_random_bytes - count); 154 memcpy(rand_gen_buf + count, randbuf, ret); 155 count += ret; 156 } 157 158 out_stop: 159 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, 160 TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGSTART_MASK, 0U); 161 162 return count; 163 } 164 165 static void xtrng_write_multiple_registers(void __iomem *base_addr, u32 *values, size_t n) 166 { 167 void __iomem *reg_addr; 168 size_t i; 169 170 /* Write seed value into EXTERNAL_SEED Registers in big endian format */ 171 for (i = 0; i < n; i++) { 172 reg_addr = (base_addr + ((n - 1 - i) * TRNG_BYTES_PER_REG)); 173 iowrite32((u32 __force)(cpu_to_be32(values[i])), reg_addr); 174 } 175 } 176 177 static void xtrng_enable_entropy(struct xilinx_rng *rng) 178 { 179 iowrite32(TRNG_OSC_EN_VAL_MASK, rng->rng_base + TRNG_OSC_EN_OFFSET); 180 xtrng_softreset(rng); 181 iowrite32(TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK, rng->rng_base + TRNG_CTRL_OFFSET); 182 } 183 184 static int xtrng_reseed_internal(struct xilinx_rng *rng) 185 { 186 static const u8 default_salt[SHA512_DIGEST_SIZE]; 187 u8 entropy[SHA512_DIGEST_SIZE] __aligned(4); 188 u32 val; 189 int ret; 190 191 xtrng_enable_entropy(rng); 192 193 /* Collect some output from the TRNG. */ 194 static_assert(sizeof(entropy) >= TRNG_SEED_LEN_BYTES); 195 ret = xtrng_collect_random_data(rng, entropy, TRNG_SEED_LEN_BYTES, true); 196 if (ret != TRNG_SEED_LEN_BYTES) 197 return -EINVAL; 198 199 /* Extract entropy from the TRNG output using HKDF-SHA512-Extract. */ 200 hmac_sha512_usingrawkey(default_salt, sizeof(default_salt), entropy, 201 TRNG_SEED_LEN_BYTES, entropy); 202 203 /* Write the extracted entropy to the hardware. */ 204 xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET, 205 (u32 *)entropy, TRNG_NUM_INIT_REGS); 206 207 /* Clear the entropy from the stack. */ 208 memzero_explicit(entropy, sizeof(entropy)); 209 210 /* select reseed operation */ 211 iowrite32(TRNG_CTRL_PRNGXS_MASK, rng->rng_base + TRNG_CTRL_OFFSET); 212 213 /* Start the reseed operation with above configuration and wait for STATUS.Done bit to be 214 * set. Monitor STATUS.CERTF bit, if set indicates SP800-90B entropy health test has failed. 215 */ 216 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, 217 TRNG_CTRL_PRNGSTART_MASK); 218 219 ret = readl_poll_timeout(rng->rng_base + TRNG_STATUS_OFFSET, val, 220 (val & TRNG_STATUS_DONE_MASK) == TRNG_STATUS_DONE_MASK, 221 1U, 15000U); 222 if (ret) 223 return ret; 224 225 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, 0U); 226 227 return 0; 228 } 229 230 static int xtrng_random_bytes_generate(struct xilinx_rng *rng, u8 *rand_buf_ptr, 231 u32 rand_buf_size, int wait) 232 { 233 int nbytes; 234 int ret; 235 236 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, 237 TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGXS_MASK, 238 TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGXS_MASK); 239 nbytes = xtrng_collect_random_data(rng, rand_buf_ptr, rand_buf_size, wait); 240 241 ret = xtrng_reseed_internal(rng); 242 if (ret) { 243 dev_err(rng->dev, "Re-seed fail\n"); 244 return ret; 245 } 246 247 return nbytes; 248 } 249 250 static int xtrng_hwrng_trng_read(struct hwrng *hwrng, void *data, size_t max, bool wait) 251 { 252 u8 buf[TRNG_SEC_STRENGTH_BYTES]; 253 struct xilinx_rng *rng; 254 int ret = 0, i = 0; 255 256 rng = container_of(hwrng, struct xilinx_rng, trng); 257 while (i < max) { 258 ret = xtrng_random_bytes_generate(rng, buf, TRNG_SEC_STRENGTH_BYTES, wait); 259 if (ret < 0) { 260 if (i == 0) 261 return ret; 262 break; 263 } 264 265 memcpy(data + i, buf, min_t(int, ret, (max - i))); 266 i += min_t(int, ret, (max - i)); 267 } 268 return i; 269 } 270 271 static int xtrng_hwrng_register(struct hwrng *trng) 272 { 273 int ret; 274 275 trng->name = "Xilinx Versal Crypto Engine TRNG"; 276 trng->read = xtrng_hwrng_trng_read; 277 278 ret = hwrng_register(trng); 279 if (ret) 280 pr_err("Fail to register the TRNG\n"); 281 282 return ret; 283 } 284 285 static void xtrng_hwrng_unregister(struct hwrng *trng) 286 { 287 hwrng_unregister(trng); 288 } 289 290 static int xtrng_probe(struct platform_device *pdev) 291 { 292 struct xilinx_rng *rng; 293 int ret; 294 295 rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); 296 if (!rng) 297 return -ENOMEM; 298 299 rng->dev = &pdev->dev; 300 rng->rng_base = devm_platform_ioremap_resource(pdev, 0); 301 if (IS_ERR(rng->rng_base)) { 302 dev_err(&pdev->dev, "Failed to map resource %pe\n", rng->rng_base); 303 return PTR_ERR(rng->rng_base); 304 } 305 306 xtrng_trng_reset(rng->rng_base); 307 ret = xtrng_reseed_internal(rng); 308 if (ret) { 309 dev_err(&pdev->dev, "TRNG Seed fail\n"); 310 return ret; 311 } 312 313 ret = xtrng_hwrng_register(&rng->trng); 314 if (ret) { 315 dev_err(&pdev->dev, "HWRNG device registration failed: %d\n", ret); 316 return ret; 317 } 318 platform_set_drvdata(pdev, rng); 319 320 return 0; 321 } 322 323 static void xtrng_remove(struct platform_device *pdev) 324 { 325 struct xilinx_rng *rng; 326 u32 zero[TRNG_NUM_INIT_REGS] = { }; 327 328 rng = platform_get_drvdata(pdev); 329 xtrng_hwrng_unregister(&rng->trng); 330 xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET, zero, 331 TRNG_NUM_INIT_REGS); 332 xtrng_write_multiple_registers(rng->rng_base + TRNG_PER_STRNG_OFFSET, zero, 333 TRNG_NUM_INIT_REGS); 334 xtrng_hold_reset(rng->rng_base); 335 } 336 337 static const struct of_device_id xtrng_of_match[] = { 338 { .compatible = "xlnx,versal-trng", }, 339 {}, 340 }; 341 342 MODULE_DEVICE_TABLE(of, xtrng_of_match); 343 344 static struct platform_driver xtrng_driver = { 345 .driver = { 346 .name = "xlnx,versal-trng", 347 .of_match_table = xtrng_of_match, 348 }, 349 .probe = xtrng_probe, 350 .remove = xtrng_remove, 351 }; 352 353 module_platform_driver(xtrng_driver); 354 MODULE_LICENSE("GPL"); 355 MODULE_AUTHOR("Harsh Jain <h.jain@amd.com>"); 356 MODULE_AUTHOR("Mounika Botcha <mounika.botcha@amd.com>"); 357 MODULE_DESCRIPTION("True Random Number Generator Driver"); 358