xref: /linux/drivers/crypto/xilinx/xilinx-trng.c (revision 6093a688a07da07808f0122f9aa2a3eed250d853)
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/errno.h>
12 #include <linux/firmware/xlnx-zynqmp.h>
13 #include <linux/hw_random.h>
14 #include <linux/io.h>
15 #include <linux/iopoll.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/mutex.h>
19 #include <linux/mod_devicetable.h>
20 #include <linux/platform_device.h>
21 #include <linux/string.h>
22 #include <crypto/internal/cipher.h>
23 #include <crypto/internal/rng.h>
24 #include <crypto/aes.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 	struct mutex lock;	/* Protect access to TRNG device */
63 	struct hwrng trng;
64 };
65 
66 struct xilinx_rng_ctx {
67 	struct xilinx_rng *rng;
68 };
69 
70 static struct xilinx_rng *xilinx_rng_dev;
71 
72 static void xtrng_readwrite32(void __iomem *addr, u32 mask, u8 value)
73 {
74 	u32 val;
75 
76 	val = ioread32(addr);
77 	val = (val & (~mask)) | (mask & value);
78 	iowrite32(val, addr);
79 }
80 
81 static void xtrng_trng_reset(void __iomem *addr)
82 {
83 	xtrng_readwrite32(addr + TRNG_RESET_OFFSET, TRNG_RESET_VAL_MASK, TRNG_RESET_VAL_MASK);
84 	udelay(TRNG_RESET_DELAY);
85 	xtrng_readwrite32(addr + TRNG_RESET_OFFSET, TRNG_RESET_VAL_MASK, 0);
86 }
87 
88 static void xtrng_hold_reset(void __iomem *addr)
89 {
90 	xtrng_readwrite32(addr + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK,
91 			  TRNG_CTRL_PRNGSRST_MASK);
92 	iowrite32(TRNG_RESET_VAL_MASK, addr + TRNG_RESET_OFFSET);
93 	udelay(TRNG_RESET_DELAY);
94 }
95 
96 static void xtrng_softreset(struct xilinx_rng *rng)
97 {
98 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK,
99 			  TRNG_CTRL_PRNGSRST_MASK);
100 	udelay(TRNG_RESET_DELAY);
101 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSRST_MASK, 0);
102 }
103 
104 /* Return no. of bytes read */
105 static size_t xtrng_readblock32(void __iomem *rng_base, __be32 *buf, int blocks32, bool wait)
106 {
107 	int read = 0, ret;
108 	int timeout = 1;
109 	int i, idx;
110 	u32 val;
111 
112 	if (wait)
113 		timeout = TRNG_DATA_READ_DELAY;
114 
115 	for (i = 0; i < (blocks32 * 2); i++) {
116 		/* TRNG core generate data in 16 bytes. Read twice to complete 32 bytes read */
117 		ret = readl_poll_timeout(rng_base + TRNG_STATUS_OFFSET, val,
118 					 (val & TRNG_STATUS_QCNT_MASK) ==
119 					 TRNG_STATUS_QCNT_16_BYTES, !!wait, timeout);
120 		if (ret)
121 			break;
122 
123 		for (idx = 0; idx < TRNG_READ_4_WORD; idx++) {
124 			*(buf + read) = cpu_to_be32(ioread32(rng_base + TRNG_CORE_OUTPUT_OFFSET));
125 			read += 1;
126 		}
127 	}
128 	return read * 4;
129 }
130 
131 static int xtrng_collect_random_data(struct xilinx_rng *rng, u8 *rand_gen_buf,
132 				     int no_of_random_bytes, bool wait)
133 {
134 	u8 randbuf[TRNG_SEC_STRENGTH_BYTES];
135 	int byteleft, blocks, count = 0;
136 	int ret;
137 
138 	byteleft = no_of_random_bytes & (TRNG_SEC_STRENGTH_BYTES - 1);
139 	blocks = no_of_random_bytes >> TRNG_SEC_STRENGTH_SHIFT;
140 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK,
141 			  TRNG_CTRL_PRNGSTART_MASK);
142 	if (blocks) {
143 		ret = xtrng_readblock32(rng->rng_base, (__be32 *)rand_gen_buf, blocks, wait);
144 		if (!ret)
145 			return 0;
146 		count += ret;
147 	}
148 
149 	if (byteleft) {
150 		ret = xtrng_readblock32(rng->rng_base, (__be32 *)randbuf, 1, wait);
151 		if (!ret)
152 			return count;
153 		memcpy(rand_gen_buf + (blocks * TRNG_SEC_STRENGTH_BYTES), randbuf, byteleft);
154 		count += byteleft;
155 	}
156 
157 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET,
158 			  TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGSTART_MASK, 0U);
159 
160 	return count;
161 }
162 
163 static void xtrng_write_multiple_registers(void __iomem *base_addr, u32 *values, size_t n)
164 {
165 	void __iomem *reg_addr;
166 	size_t i;
167 
168 	/* Write seed value into EXTERNAL_SEED Registers in big endian format */
169 	for (i = 0; i < n; i++) {
170 		reg_addr = (base_addr + ((n - 1 - i) * TRNG_BYTES_PER_REG));
171 		iowrite32((u32 __force)(cpu_to_be32(values[i])), reg_addr);
172 	}
173 }
174 
175 static void xtrng_enable_entropy(struct xilinx_rng *rng)
176 {
177 	iowrite32(TRNG_OSC_EN_VAL_MASK, rng->rng_base + TRNG_OSC_EN_OFFSET);
178 	xtrng_softreset(rng);
179 	iowrite32(TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK, rng->rng_base + TRNG_CTRL_OFFSET);
180 }
181 
182 static int xtrng_reseed_internal(struct xilinx_rng *rng)
183 {
184 	u8 entropy[TRNG_ENTROPY_SEED_LEN_BYTES];
185 	u32 val;
186 	int ret;
187 
188 	memset(entropy, 0, sizeof(entropy));
189 	xtrng_enable_entropy(rng);
190 
191 	/* collect random data to use it as entropy (input for DF) */
192 	ret = xtrng_collect_random_data(rng, entropy, TRNG_SEED_LEN_BYTES, true);
193 	if (ret != TRNG_SEED_LEN_BYTES)
194 		return -EINVAL;
195 
196 	xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET,
197 				       (u32 *)entropy, TRNG_NUM_INIT_REGS);
198 	/* select reseed operation */
199 	iowrite32(TRNG_CTRL_PRNGXS_MASK, rng->rng_base + TRNG_CTRL_OFFSET);
200 
201 	/* Start the reseed operation with above configuration and wait for STATUS.Done bit to be
202 	 * set. Monitor STATUS.CERTF bit, if set indicates SP800-90B entropy health test has failed.
203 	 */
204 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK,
205 			  TRNG_CTRL_PRNGSTART_MASK);
206 
207 	ret = readl_poll_timeout(rng->rng_base + TRNG_STATUS_OFFSET, val,
208 				 (val & TRNG_STATUS_DONE_MASK) == TRNG_STATUS_DONE_MASK,
209 				  1U, 15000U);
210 	if (ret)
211 		return ret;
212 
213 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET, TRNG_CTRL_PRNGSTART_MASK, 0U);
214 
215 	return 0;
216 }
217 
218 static int xtrng_random_bytes_generate(struct xilinx_rng *rng, u8 *rand_buf_ptr,
219 				       u32 rand_buf_size, int wait)
220 {
221 	int nbytes;
222 	int ret;
223 
224 	xtrng_readwrite32(rng->rng_base + TRNG_CTRL_OFFSET,
225 			  TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGXS_MASK,
226 			  TRNG_CTRL_PRNGMODE_MASK | TRNG_CTRL_PRNGXS_MASK);
227 	nbytes = xtrng_collect_random_data(rng, rand_buf_ptr, rand_buf_size, wait);
228 
229 	ret = xtrng_reseed_internal(rng);
230 	if (ret) {
231 		dev_err(rng->dev, "Re-seed fail\n");
232 		return ret;
233 	}
234 
235 	return nbytes;
236 }
237 
238 static int xtrng_trng_generate(struct crypto_rng *tfm, const u8 *src, u32 slen,
239 			       u8 *dst, u32 dlen)
240 {
241 	struct xilinx_rng_ctx *ctx = crypto_rng_ctx(tfm);
242 	int ret;
243 
244 	mutex_lock(&ctx->rng->lock);
245 	ret = xtrng_random_bytes_generate(ctx->rng, dst, dlen, true);
246 	mutex_unlock(&ctx->rng->lock);
247 
248 	return ret < 0 ? ret : 0;
249 }
250 
251 static int xtrng_trng_seed(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
252 {
253 	return 0;
254 }
255 
256 static int xtrng_trng_init(struct crypto_tfm *rtfm)
257 {
258 	struct xilinx_rng_ctx *ctx = crypto_tfm_ctx(rtfm);
259 
260 	ctx->rng = xilinx_rng_dev;
261 
262 	return 0;
263 }
264 
265 static struct rng_alg xtrng_trng_alg = {
266 	.generate = xtrng_trng_generate,
267 	.seed = xtrng_trng_seed,
268 	.seedsize = 0,
269 	.base = {
270 		.cra_name = "stdrng",
271 		.cra_driver_name = "xilinx-trng",
272 		.cra_priority = 300,
273 		.cra_ctxsize = sizeof(struct xilinx_rng_ctx),
274 		.cra_module = THIS_MODULE,
275 		.cra_init = xtrng_trng_init,
276 	},
277 };
278 
279 static int xtrng_hwrng_trng_read(struct hwrng *hwrng, void *data, size_t max, bool wait)
280 {
281 	u8 buf[TRNG_SEC_STRENGTH_BYTES];
282 	struct xilinx_rng *rng;
283 	int ret = -EINVAL, i = 0;
284 
285 	rng = container_of(hwrng, struct xilinx_rng, trng);
286 	/* Return in case wait not set and lock not available. */
287 	if (!mutex_trylock(&rng->lock) && !wait)
288 		return 0;
289 	else if (!mutex_is_locked(&rng->lock) && wait)
290 		mutex_lock(&rng->lock);
291 
292 	while (i < max) {
293 		ret = xtrng_random_bytes_generate(rng, buf, TRNG_SEC_STRENGTH_BYTES, wait);
294 		if (ret < 0)
295 			break;
296 
297 		memcpy(data + i, buf, min_t(int, ret, (max - i)));
298 		i += min_t(int, ret, (max - i));
299 	}
300 	mutex_unlock(&rng->lock);
301 
302 	return ret;
303 }
304 
305 static int xtrng_hwrng_register(struct hwrng *trng)
306 {
307 	int ret;
308 
309 	trng->name = "Xilinx Versal Crypto Engine TRNG";
310 	trng->read = xtrng_hwrng_trng_read;
311 
312 	ret = hwrng_register(trng);
313 	if (ret)
314 		pr_err("Fail to register the TRNG\n");
315 
316 	return ret;
317 }
318 
319 static void xtrng_hwrng_unregister(struct hwrng *trng)
320 {
321 	hwrng_unregister(trng);
322 }
323 
324 static int xtrng_probe(struct platform_device *pdev)
325 {
326 	struct xilinx_rng *rng;
327 	int ret;
328 
329 	rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
330 	if (!rng)
331 		return -ENOMEM;
332 
333 	rng->dev = &pdev->dev;
334 	rng->rng_base = devm_platform_ioremap_resource(pdev, 0);
335 	if (IS_ERR(rng->rng_base)) {
336 		dev_err(&pdev->dev, "Failed to map resource %ld\n", PTR_ERR(rng->rng_base));
337 		return PTR_ERR(rng->rng_base);
338 	}
339 
340 	xtrng_trng_reset(rng->rng_base);
341 	ret = xtrng_reseed_internal(rng);
342 	if (ret) {
343 		dev_err(&pdev->dev, "TRNG Seed fail\n");
344 		return ret;
345 	}
346 
347 	xilinx_rng_dev = rng;
348 	mutex_init(&rng->lock);
349 	ret = crypto_register_rng(&xtrng_trng_alg);
350 	if (ret) {
351 		dev_err(&pdev->dev, "Crypto Random device registration failed: %d\n", ret);
352 		return ret;
353 	}
354 	ret = xtrng_hwrng_register(&rng->trng);
355 	if (ret) {
356 		dev_err(&pdev->dev, "HWRNG device registration failed: %d\n", ret);
357 		goto crypto_rng_free;
358 	}
359 	platform_set_drvdata(pdev, rng);
360 
361 	return 0;
362 
363 crypto_rng_free:
364 	crypto_unregister_rng(&xtrng_trng_alg);
365 
366 	return ret;
367 }
368 
369 static void xtrng_remove(struct platform_device *pdev)
370 {
371 	struct xilinx_rng *rng;
372 	u32 zero[TRNG_NUM_INIT_REGS] = { };
373 
374 	rng = platform_get_drvdata(pdev);
375 	xtrng_hwrng_unregister(&rng->trng);
376 	crypto_unregister_rng(&xtrng_trng_alg);
377 	xtrng_write_multiple_registers(rng->rng_base + TRNG_EXT_SEED_OFFSET, zero,
378 				       TRNG_NUM_INIT_REGS);
379 	xtrng_write_multiple_registers(rng->rng_base + TRNG_PER_STRNG_OFFSET, zero,
380 				       TRNG_NUM_INIT_REGS);
381 	xtrng_hold_reset(rng->rng_base);
382 	xilinx_rng_dev = NULL;
383 }
384 
385 static const struct of_device_id xtrng_of_match[] = {
386 	{ .compatible = "xlnx,versal-trng", },
387 	{},
388 };
389 
390 MODULE_DEVICE_TABLE(of, xtrng_of_match);
391 
392 static struct platform_driver xtrng_driver = {
393 	.driver = {
394 		.name = "xlnx,versal-trng",
395 		.of_match_table	= xtrng_of_match,
396 	},
397 	.probe = xtrng_probe,
398 	.remove = xtrng_remove,
399 };
400 
401 module_platform_driver(xtrng_driver);
402 MODULE_LICENSE("GPL");
403 MODULE_AUTHOR("Harsh Jain <h.jain@amd.com>");
404 MODULE_AUTHOR("Mounika Botcha <mounika.botcha@amd.com>");
405 MODULE_DESCRIPTION("True Random Number Generator Driver");
406