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