xref: /linux/drivers/char/hw_random/xilinx-trng.c (revision c7fdfd2bee1cf1448e5244da1a734e680f634b02)
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