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 <linux/bitfield.h> 8 #include <linux/clk.h> 9 #include <linux/crypto.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/mutex.h> 18 #include <linux/mod_devicetable.h> 19 #include <linux/platform_device.h> 20 #include <crypto/aes.h> 21 #include <crypto/df_sp80090a.h> 22 #include <crypto/internal/drbg.h> 23 #include <crypto/internal/cipher.h> 24 #include <crypto/internal/rng.h> 25 26 /* TRNG Registers Offsets */ 27 #define TRNG_STATUS_OFFSET 0x4U 28 #define TRNG_CTRL_OFFSET 0x8U 29 #define TRNG_EXT_SEED_OFFSET 0x40U 30 #define TRNG_PER_STRNG_OFFSET 0x80U 31 #define TRNG_CORE_OUTPUT_OFFSET 0xC0U 32 #define TRNG_RESET_OFFSET 0xD0U 33 #define TRNG_OSC_EN_OFFSET 0xD4U 34 35 /* Mask values */ 36 #define TRNG_RESET_VAL_MASK BIT(0) 37 #define TRNG_OSC_EN_VAL_MASK BIT(0) 38 #define TRNG_CTRL_PRNGSRST_MASK BIT(0) 39 #define TRNG_CTRL_EUMODE_MASK BIT(8) 40 #define TRNG_CTRL_TRSSEN_MASK BIT(2) 41 #define TRNG_CTRL_PRNGSTART_MASK BIT(5) 42 #define TRNG_CTRL_PRNGXS_MASK BIT(3) 43 #define TRNG_CTRL_PRNGMODE_MASK BIT(7) 44 #define TRNG_STATUS_DONE_MASK BIT(0) 45 #define TRNG_STATUS_QCNT_MASK GENMASK(11, 9) 46 #define TRNG_STATUS_QCNT_16_BYTES 0x800 47 48 /* Sizes in bytes */ 49 #define TRNG_SEED_LEN_BYTES 48U 50 #define TRNG_ENTROPY_SEED_LEN_BYTES 64U 51 #define TRNG_SEC_STRENGTH_SHIFT 5U 52 #define TRNG_SEC_STRENGTH_BYTES BIT(TRNG_SEC_STRENGTH_SHIFT) 53 #define TRNG_BYTES_PER_REG 4U 54 #define TRNG_RESET_DELAY 10 55 #define TRNG_NUM_INIT_REGS 12U 56 #define TRNG_READ_4_WORD 4 57 #define TRNG_DATA_READ_DELAY 8000 58 59 struct xilinx_rng { 60 void __iomem *rng_base; 61 struct device *dev; 62 unsigned char *scratchpadbuf; 63 struct crypto_aes_ctx *aesctx; 64 struct mutex lock; /* Protect access to TRNG device */ 65 struct hwrng trng; 66 }; 67 68 struct xilinx_rng_ctx { 69 struct xilinx_rng *rng; 70 }; 71 72 static struct xilinx_rng *xilinx_rng_dev; 73 74 static void xtrng_readwrite32(void __iomem *addr, u32 mask, u8 value) 75 { 76 u32 val; 77 78 val = ioread32(addr); 79 val = (val & (~mask)) | (mask & value); 80 iowrite32(val, addr); 81 } 82 83 static void xtrng_trng_reset(void __iomem *addr) 84 { 85 xtrng_readwrite32(addr + TRNG_RESET_OFFSET, TRNG_RESET_VAL_MASK, TRNG_RESET_VAL_MASK); 86 udelay(TRNG_RESET_DELAY); 87 xtrng_readwrite32(addr + TRNG_RESET_OFFSET, TRNG_RESET_VAL_MASK, 0); 88 } 89 90 static void xtrng_hold_reset(void __iomem *addr) 91 { 92 xtrng_readwrite32(addr + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 93 TRNG_CTRL_PRNGSRST_MASK); 94 iowrite32(TRNG_RESET_VAL_MASK, addr + TRNG_RESET_OFFSET); 95 udelay(TRNG_RESET_DELAY); 96 } 97 98 static void xtrng_softreset(struct xilinx_rng *rng) 99 { 100 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 101 TRNG_CTRL_PRNGSRST_MASK); 102 udelay(TRNG_RESET_DELAY); 103 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 0); 104 } 105 106 /* Return no. of bytes read */ 107 static size_t xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32, bool wait) 108 { 109 int read = 0, ret; 110 int timeout = 1; 111 int i, idx; 112 u32 val; 113 114 if (wait) 115 timeout = TRNG_DATA_READ_DELAY; 116 117 for (i = 0; i < (blocks32 * 2); i++) { 118 /* TRNG core generate data in 16 bytes. Read twice to complete 32 bytes read */ 119 ret = readl_poll_timeout(rng_base + TRNG_STATUS_OFFSET, val, 120 (val & TRNG_STATUS_QCNT_MASK) == 121 TRNG_STATUS_QCNT_16_BYTES, !!wait, timeout); 122 if (ret) 123 break; 124 125 for (idx = 0; idx < TRNG_READ_4_WORD; idx++) { 126 *(buf + read) = cpu_to_be32(ioread32(rng_base + TRNG_CORE_OUTPUT_OFFSET)); 127 read += 1; 128 } 129 } 130 return read * 4; 131 } 132 133 static int xtrng_collect_random_data(struct xilinx_rng *rng, u8 *rand_gen_buf, 134 int no_of_random_bytes, bool wait) 135 { 136 u8 randbuf[TRNG_SEC_STRENGTH_BYTES]; 137 int byteleft, blocks, count = 0; 138 int ret; 139 140 byteleft = no_of_random_bytes & (TRNG_SEC_STRENGTH_BYTES - 1); 141 blocks = no_of_random_bytes >> TRNG_SEC_STRENGTH_SHIFT; 142 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, 143 TRNG_CTRL_PRNGSTART_MASK); 144 if (blocks) { 145 ret = xtrng_readblock32(rng->rng_base, (__be32 *)rand_gen_buf, blocks, wait); 146 if (!ret) 147 return 0; 148 count += ret; 149 } 150 151 if (byteleft) { 152 ret = xtrng_readblock32(rng->rng_base, (__be32 *)randbuf, 1, wait); 153 if (!ret) 154 return count; 155 memcpy(rand_gen_buf + (blocks * TRNG_SEC_STRENGTH_BYTES), randbuf, byteleft); 156 count += byteleft; 157 } 158 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 u8 entropy[TRNG_ENTROPY_SEED_LEN_BYTES]; 187 struct drbg_string data; 188 LIST_HEAD(seedlist); 189 u32 val; 190 int ret; 191 192 drbg_string_fill(&data, entropy, TRNG_SEED_LEN_BYTES); 193 list_add_tail(&data.list, &seedlist); 194 memset(entropy, 0, sizeof(entropy)); 195 xtrng_enable_entropy(rng); 196 197 /* collect random data to use it as entropy (input for DF) */ 198 ret = xtrng_collect_random_data(rng, entropy, TRNG_SEED_LEN_BYTES, true); 199 if (ret != TRNG_SEED_LEN_BYTES) 200 return -EINVAL; 201 ret = crypto_drbg_ctr_df(rng->aesctx, rng->scratchpadbuf, 202 TRNG_SEED_LEN_BYTES, &seedlist, AES_BLOCK_SIZE, 203 TRNG_SEED_LEN_BYTES); 204 if (ret) 205 return ret; 206 207 xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET, 208 (u32 *)rng->scratchpadbuf, TRNG_NUM_INIT_REGS); 209 /* select reseed operation */ 210 iowrite32(TRNG_CTRL_PRNGXS_MASK, rng->rng_base + TRNG_CTRL_OFFSET); 211 212 /* Start the reseed operation with above configuration and wait for STATUS.Done bit to be 213 * set. Monitor STATUS.CERTF bit, if set indicates SP800-90B entropy health test has failed. 214 */ 215 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, 216 TRNG_CTRL_PRNGSTART_MASK); 217 218 ret = readl_poll_timeout(rng->rng_base + TRNG_STATUS_OFFSET, val, 219 (val & TRNG_STATUS_DONE_MASK) == TRNG_STATUS_DONE_MASK, 220 1U, 15000U); 221 if (ret) 222 return ret; 223 224 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, 0U); 225 226 return 0; 227 } 228 229 static int xtrng_random_bytes_generate(struct xilinx_rng *rng, u8 *rand_buf_ptr, 230 u32 rand_buf_size, int wait) 231 { 232 int nbytes; 233 int ret; 234 235 xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, 236 TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGXS_MASK, 237 TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGXS_MASK); 238 nbytes = xtrng_collect_random_data(rng, rand_buf_ptr, rand_buf_size, wait); 239 240 ret = xtrng_reseed_internal(rng); 241 if (ret) { 242 dev_err(rng->dev, "Re-seed fail\n"); 243 return ret; 244 } 245 246 return nbytes; 247 } 248 249 static int xtrng_trng_generate(struct crypto_rng *tfm, const u8 *src, u32 slen, 250 u8 *dst, u32 dlen) 251 { 252 struct xilinx_rng_ctx *ctx = crypto_rng_ctx(tfm); 253 int ret; 254 255 mutex_lock(&ctx->rng->lock); 256 ret = xtrng_random_bytes_generate(ctx->rng, dst, dlen, true); 257 mutex_unlock(&ctx->rng->lock); 258 259 return ret < 0 ? ret : 0; 260 } 261 262 static int xtrng_trng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen) 263 { 264 return 0; 265 } 266 267 static int xtrng_trng_init(struct crypto_tfm *rtfm) 268 { 269 struct xilinx_rng_ctx *ctx = crypto_tfm_ctx(rtfm); 270 271 ctx->rng = xilinx_rng_dev; 272 273 return 0; 274 } 275 276 static struct rng_alg xtrng_trng_alg = { 277 .generate = xtrng_trng_generate, 278 .seed = xtrng_trng_seed, 279 .seedsize = 0, 280 .base = { 281 .cra_name = "stdrng", 282 .cra_driver_name = "xilinx-trng", 283 .cra_priority = 300, 284 .cra_ctxsize = sizeof(struct xilinx_rng_ctx), 285 .cra_module = THIS_MODULE, 286 .cra_init = xtrng_trng_init, 287 }, 288 }; 289 290 static int xtrng_hwrng_trng_read(struct hwrng *hwrng, void *data, size_t max, bool wait) 291 { 292 u8 buf[TRNG_SEC_STRENGTH_BYTES]; 293 struct xilinx_rng *rng; 294 int ret = -EINVAL, i = 0; 295 296 rng = container_of(hwrng, struct xilinx_rng, trng); 297 /* Return in case wait not set and lock not available. */ 298 if (!mutex_trylock(&rng->lock) && !wait) 299 return 0; 300 else if (!mutex_is_locked(&rng->lock) && wait) 301 mutex_lock(&rng->lock); 302 303 while (i < max) { 304 ret = xtrng_random_bytes_generate(rng, buf, TRNG_SEC_STRENGTH_BYTES, wait); 305 if (ret < 0) 306 break; 307 308 memcpy(data + i, buf, min_t(int, ret, (max - i))); 309 i += min_t(int, ret, (max - i)); 310 } 311 mutex_unlock(&rng->lock); 312 313 return ret; 314 } 315 316 static int xtrng_hwrng_register(struct hwrng *trng) 317 { 318 int ret; 319 320 trng->name = "Xilinx Versal Crypto Engine TRNG"; 321 trng->read = xtrng_hwrng_trng_read; 322 323 ret = hwrng_register(trng); 324 if (ret) 325 pr_err("Fail to register the TRNG\n"); 326 327 return ret; 328 } 329 330 static void xtrng_hwrng_unregister(struct hwrng *trng) 331 { 332 hwrng_unregister(trng); 333 } 334 335 static int xtrng_probe(struct platform_device *pdev) 336 { 337 struct xilinx_rng *rng; 338 size_t sb_size; 339 int ret; 340 341 rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); 342 if (!rng) 343 return -ENOMEM; 344 345 rng->dev = &pdev->dev; 346 rng->rng_base = devm_platform_ioremap_resource(pdev, 0); 347 if (IS_ERR(rng->rng_base)) { 348 dev_err(&pdev->dev, "Failed to map resource %ld\n", PTR_ERR(rng->rng_base)); 349 return PTR_ERR(rng->rng_base); 350 } 351 352 rng->aesctx = devm_kzalloc(&pdev->dev, sizeof(*rng->aesctx), GFP_KERNEL); 353 if (!rng->aesctx) 354 return -ENOMEM; 355 356 sb_size = crypto_drbg_ctr_df_datalen(TRNG_SEED_LEN_BYTES, AES_BLOCK_SIZE); 357 rng->scratchpadbuf = devm_kzalloc(&pdev->dev, sb_size, GFP_KERNEL); 358 if (!rng->scratchpadbuf) { 359 ret = -ENOMEM; 360 goto end; 361 } 362 363 xtrng_trng_reset(rng->rng_base); 364 ret = xtrng_reseed_internal(rng); 365 if (ret) { 366 dev_err(&pdev->dev, "TRNG Seed fail\n"); 367 goto end; 368 } 369 370 xilinx_rng_dev = rng; 371 mutex_init(&rng->lock); 372 ret = crypto_register_rng(&xtrng_trng_alg); 373 if (ret) { 374 dev_err(&pdev->dev, "Crypto Random device registration failed: %d\n", ret); 375 goto end; 376 } 377 378 ret = xtrng_hwrng_register(&rng->trng); 379 if (ret) { 380 dev_err(&pdev->dev, "HWRNG device registration failed: %d\n", ret); 381 goto crypto_rng_free; 382 } 383 platform_set_drvdata(pdev, rng); 384 385 return 0; 386 387 crypto_rng_free: 388 crypto_unregister_rng(&xtrng_trng_alg); 389 390 end: 391 return ret; 392 } 393 394 static void xtrng_remove(struct platform_device *pdev) 395 { 396 struct xilinx_rng *rng; 397 u32 zero[TRNG_NUM_INIT_REGS] = { }; 398 399 rng = platform_get_drvdata(pdev); 400 xtrng_hwrng_unregister(&rng->trng); 401 crypto_unregister_rng(&xtrng_trng_alg); 402 xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET, zero, 403 TRNG_NUM_INIT_REGS); 404 xtrng_write_multiple_registers(rng->rng_base + TRNG_PER_STRNG_OFFSET, zero, 405 TRNG_NUM_INIT_REGS); 406 xtrng_hold_reset(rng->rng_base); 407 xilinx_rng_dev = NULL; 408 } 409 410 static const struct of_device_id xtrng_of_match[] = { 411 { .compatible = "xlnx,versal-trng", }, 412 {}, 413 }; 414 415 MODULE_DEVICE_TABLE(of, xtrng_of_match); 416 417 static struct platform_driver xtrng_driver = { 418 .driver = { 419 .name = "xlnx,versal-trng", 420 .of_match_table = xtrng_of_match, 421 }, 422 .probe = xtrng_probe, 423 .remove = xtrng_remove, 424 }; 425 426 module_platform_driver(xtrng_driver); 427 MODULE_LICENSE("GPL"); 428 MODULE_AUTHOR("Harsh Jain <h.jain@amd.com>"); 429 MODULE_AUTHOR("Mounika Botcha <mounika.botcha@amd.com>"); 430 MODULE_DESCRIPTION("True Random Number Generator Driver"); 431