1 /*
2  * Copyright (c) 2023-2024 Analog Devices, Inc.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <zephyr/sys/util.h>
9 
10 #define DT_DRV_COMPAT adi_max32_trng
11 
12 #include <zephyr/device.h>
13 #include <zephyr/drivers/entropy.h>
14 #include <zephyr/drivers/clock_control/adi_max32_clock_control.h>
15 
16 #include <wrap_max32_trng.h>
17 
18 struct max32_trng_config {
19 	const struct device *clock;
20 	struct max32_perclk perclk;
21 };
22 
api_get_entropy(const struct device * dev,uint8_t * buf,uint16_t len)23 static int api_get_entropy(const struct device *dev, uint8_t *buf, uint16_t len)
24 {
25 	return MXC_TRNG_Random(buf, len);
26 }
27 
api_get_entropy_isr(const struct device * dev,uint8_t * buf,uint16_t len,uint32_t flags)28 static int api_get_entropy_isr(const struct device *dev, uint8_t *buf, uint16_t len, uint32_t flags)
29 {
30 	int ret = 0;
31 
32 	if ((flags & ENTROPY_BUSYWAIT) == 0) {
33 		uint32_t temp;
34 		uint32_t copy_len;
35 		uint32_t count = 0;
36 
37 		while (len) {
38 			ret = Wrap_MXC_TRNG_RandomInt_NonBlocking(&temp);
39 			if (ret != 0) {
40 				break; /* Data not ready do not wait */
41 			}
42 
43 			copy_len = MIN(len, 4);
44 			memcpy(buf, (uint8_t *)&temp, copy_len);
45 
46 			len -= copy_len;
47 			buf += copy_len;
48 			count += copy_len;
49 		}
50 
51 		/* User would like to read len bytes but in non-blocking mode
52 		 *  the function might read less, in that case return value will be
53 		 *  number of bytes read, if its 0 that means no data reads function
54 		 *  will return -ENODATA
55 		 */
56 		ret = count ? count : -ENODATA;
57 	} else {
58 		/* Allowed to busy-wait */
59 		ret = api_get_entropy(dev, buf, len);
60 		if (ret == 0) {
61 			ret = len; /* Data retrieved successfully. */
62 		}
63 	}
64 
65 	return ret;
66 }
67 
68 static DEVICE_API(entropy, entropy_max32_api) = {.get_entropy = api_get_entropy,
69 							    .get_entropy_isr = api_get_entropy_isr};
70 
entropy_max32_init(const struct device * dev)71 static int entropy_max32_init(const struct device *dev)
72 {
73 	int ret;
74 	const struct max32_trng_config *cfg = dev->config;
75 
76 	/* Enable clock */
77 	ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->perclk);
78 
79 	return ret;
80 }
81 
82 static const struct max32_trng_config max32_trng_cfg = {
83 	.clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)),
84 	.perclk.bus = DT_INST_CLOCKS_CELL(0, offset),
85 	.perclk.bit = DT_INST_CLOCKS_CELL(0, bit),
86 };
87 
88 DEVICE_DT_INST_DEFINE(0, entropy_max32_init, NULL, NULL, &max32_trng_cfg, PRE_KERNEL_1,
89 		      CONFIG_ENTROPY_INIT_PRIORITY, &entropy_max32_api);
90