Skip to content

Commit 4cd810a

Browse files
drivers: platform: maxim: max32657: Add CAPI TRNG driver
Add the implementation for the CAPI TRNG driver Signed-off-by: Ramon Miguel Imbao <ramonmiguel.imbao@analog.com>
1 parent f5fa3dc commit 4cd810a

2 files changed

Lines changed: 371 additions & 0 deletions

File tree

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
/*******************************************************************************
2+
* @file maxim_capi_trng.c
3+
* @brief Implementation of TRNG functions
4+
* @author Ramon Miguel Imbao (ramonmiguel.imbao@analog.com)
5+
********************************************************************************
6+
* Copyright 2026(c) Analog Devices, Inc.
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
*
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* 3. Neither the name of Analog Devices, Inc. nor the names of its
19+
* contributors may be used to endorse or promote products derived from this
20+
* software without specific prior written permission.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
23+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
25+
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
26+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28+
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31+
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
*******************************************************************************/
33+
34+
#include <stdlib.h>
35+
#include <errno.h>
36+
#include "capi_trng.h"
37+
#include "maxim_capi_trng.h"
38+
#include "maxim_capi_irq.h"
39+
#include "trng.h"
40+
#include "max32657.h"
41+
42+
/** Static variables **********************************************************/
43+
44+
static struct capi_trng_handle *trng = NULL;
45+
46+
/** Forward declarations ******************************************************/
47+
48+
void max_capi_trng_isr(void *handle);
49+
50+
/** Helper functions **********************************************************/
51+
52+
/**
53+
* @brief Callback function to pass to MXC_TRNG_RandomAsync
54+
* @param req MSDK-managed parameter (not used)
55+
* @param result The result of the callback
56+
*/
57+
static void _max_capi_trng_msdk_callback(void *req, int result)
58+
{
59+
struct max_capi_trng_priv *trng_priv;
60+
enum capi_trng_async_event event;
61+
62+
if (!trng || !trng->priv)
63+
return;
64+
65+
trng_priv = trng->priv;
66+
67+
if (trng_priv->callback) {
68+
event = (result == E_NO_ERROR)
69+
? CAPI_TRNG_EVENT_GENERATION_COMPLETE
70+
: CAPI_TRNG_EVENT_ERROR;
71+
trng_priv->callback(event, trng_priv->callback_arg, result);
72+
}
73+
}
74+
75+
/** Function implementations **************************************************/
76+
77+
/**
78+
* @brief Initialize the TRNG peripheral
79+
* @param handle Pointer to the TRNG handle
80+
* @param config Configuration struct
81+
* @return 0 on success, negative error code otherwise
82+
*/
83+
int max_capi_trng_init(struct capi_trng_handle **handle,
84+
const struct capi_trng_config *config)
85+
{
86+
int ret;
87+
struct capi_trng_handle *trng_handle;
88+
struct max_capi_trng_priv *trng_priv;
89+
90+
if (!handle || !config)
91+
return -EINVAL;
92+
93+
if (config->identifier != 0)
94+
return -EINVAL;
95+
96+
if (trng != NULL) {
97+
*handle = trng;
98+
return 0;
99+
}
100+
101+
if (*handle == NULL) {
102+
trng_handle = capi_calloc(1, sizeof(*trng_handle));
103+
if (!trng_handle)
104+
return -ENOMEM;
105+
trng_handle->init_allocated = true;
106+
} else {
107+
trng_handle = *handle;
108+
trng_handle->init_allocated = false;
109+
}
110+
111+
trng_priv = capi_calloc(1, sizeof(*trng_priv));
112+
if (!trng_priv) {
113+
ret = -ENOMEM;
114+
goto free_handle;
115+
}
116+
117+
trng_handle->priv = trng_priv;
118+
trng_handle->ops = config->ops;
119+
120+
ret = MXC_TRNG_Init();
121+
if (ret)
122+
goto free_priv;
123+
124+
struct capi_irq_config irq_config = {
125+
.irq_ctrl_id = 0,
126+
};
127+
128+
ret = capi_irq_init(&irq_config);
129+
if (ret)
130+
goto free_priv;
131+
132+
ret = capi_irq_connect(TRNG_IRQn, max_capi_trng_isr, trng_handle);
133+
if (ret)
134+
goto free_priv;
135+
136+
ret = capi_irq_set_priority(TRNG_IRQn, config->irq_priority);
137+
if (ret)
138+
goto disconnect_irq;
139+
140+
ret = capi_irq_enable(TRNG_IRQn);
141+
if (ret)
142+
goto disconnect_irq;
143+
144+
trng = trng_handle;
145+
*handle = trng_handle;
146+
147+
return 0;
148+
149+
disconnect_irq:
150+
capi_irq_connect(TRNG_IRQn, NULL, NULL);
151+
free_priv:
152+
MXC_TRNG_Shutdown();
153+
capi_free(trng_priv);
154+
free_handle:
155+
if (trng_handle->init_allocated)
156+
capi_free(trng_handle);
157+
158+
trng = NULL;
159+
160+
return ret;
161+
}
162+
163+
/**
164+
* @brief Deinitialize the TRNG peripheral
165+
* @param handle The TRNG handle
166+
* @return 0 on success, negative error code otherwise
167+
*/
168+
int max_capi_trng_deinit(struct capi_trng_handle *handle)
169+
{
170+
int ret;
171+
struct max_capi_trng_priv *trng_priv;
172+
173+
if (!handle || !handle->priv)
174+
return -EINVAL;
175+
176+
trng_priv = handle->priv;
177+
178+
capi_irq_disable(TRNG_IRQn);
179+
capi_irq_connect(TRNG_IRQn, NULL, NULL);
180+
181+
ret = MXC_TRNG_Shutdown();
182+
183+
capi_free(handle->priv);
184+
185+
if (handle->init_allocated)
186+
capi_free(handle);
187+
188+
trng = NULL;
189+
190+
return ret;
191+
}
192+
193+
/**
194+
* @brief Generate an unsigned 32-bit number (blocking)
195+
* @param handle The TRNG handle
196+
* @param value Where to store the unsigned 32-bit number
197+
* @return 0 on success, negative error code otherwise
198+
*/
199+
int max_capi_trng_generate_u32(struct capi_trng_handle *handle, uint32_t *value)
200+
{
201+
if (!handle || !handle->priv || !value)
202+
return -EINVAL;
203+
204+
*value = (uint32_t)MXC_TRNG_RandomInt();
205+
206+
return 0;
207+
}
208+
209+
/**
210+
* @brief Fill a buffer with random bytes (blocking)
211+
* @param handle The TRNG handle
212+
* @param buffer The data buffer to store bytes to
213+
* @param length The length of the buffer
214+
* @return 0 on success, negative error code otherwise
215+
*/
216+
int max_capi_trng_fill_buffer(struct capi_trng_handle *handle, uint8_t *buffer,
217+
uint32_t length)
218+
{
219+
int ret;
220+
221+
if (!handle || !handle->priv || !buffer)
222+
return -EINVAL;
223+
224+
if (length == 0)
225+
return -EINVAL;
226+
227+
ret = MXC_TRNG_Random(buffer, length);
228+
if (ret != E_NO_ERROR)
229+
return -EINVAL;
230+
231+
return 0;
232+
}
233+
234+
/**
235+
* @brief Fill a buffer with random bytes (non-blocking)
236+
* @param handle The TRNG handle
237+
* @param buffer The data buffer to store bytes to
238+
* @param length The length of the buffer
239+
* @return 0 on success, negative error code otherwise
240+
*/
241+
int max_capi_trng_fill_buffer_async(struct capi_trng_handle *handle,
242+
uint8_t *buffer, uint32_t length)
243+
{
244+
if (!handle || !handle->priv || !buffer)
245+
return -EINVAL;
246+
247+
if (length == 0)
248+
return -EINVAL;
249+
250+
MXC_TRNG_RandomAsync(buffer, length, _max_capi_trng_msdk_callback);
251+
252+
return 0;
253+
}
254+
255+
/**
256+
* @brief Register a callback
257+
* @param handle The TRNG handle
258+
* @param callback The callback function
259+
* @param callback_arg The callback function argument
260+
* @return 0 on success, negative error code otherwise
261+
*/
262+
int max_capi_trng_register_callback(struct capi_trng_handle *handle,
263+
capi_trng_callback_t callback,
264+
void *callback_arg)
265+
{
266+
struct max_capi_trng_priv *trng_priv;
267+
268+
if (!handle || !handle->priv)
269+
return -EINVAL;
270+
271+
trng_priv = handle->priv;
272+
273+
trng_priv->callback = callback;
274+
trng_priv->callback_arg = callback_arg;
275+
276+
return 0;
277+
}
278+
279+
/**
280+
* @brief Perform entropy source health test
281+
* @param handle The TRNG handle
282+
* @return 0 on success, negative error code otherwise
283+
*/
284+
int max_capi_trng_health_test(struct capi_trng_handle *handle)
285+
{
286+
int ret;
287+
288+
if (!handle || !handle->priv)
289+
return -EINVAL;
290+
291+
ret = MXC_TRNG_HealthTest();
292+
if (ret != E_NO_ERROR)
293+
return -EINVAL;
294+
295+
return 0;
296+
}
297+
298+
/**
299+
* @brief Interrupt handler for the TRNG peripheral
300+
* @param handle The TRNG handle
301+
*/
302+
void max_capi_trng_isr(void *handle)
303+
{
304+
struct capi_trng_handle *trng_handle = (struct capi_trng_handle *)handle;
305+
306+
if (!trng_handle || !trng_handle->priv)
307+
return;
308+
309+
MXC_TRNG_Handler();
310+
}
311+
312+
const struct capi_trng_ops max_capi_trng_ops = {
313+
.init = max_capi_trng_init,
314+
.deinit = max_capi_trng_deinit,
315+
.generate_u32 = max_capi_trng_generate_u32,
316+
.fill_buffer = max_capi_trng_fill_buffer,
317+
.fill_buffer_async = max_capi_trng_fill_buffer_async,
318+
.register_callback = max_capi_trng_register_callback,
319+
.health_test = max_capi_trng_health_test,
320+
.isr = max_capi_trng_isr,
321+
};
322+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*******************************************************************************
2+
* @file maxim_capi_trng.h
3+
* @brief Header file for TRNG functions
4+
* @author Ramon Miguel Imbao (ramonmiguel.imbao@analog.com)
5+
********************************************************************************
6+
* Copyright 2026(c) Analog Devices, Inc.
7+
*
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
*
14+
* 2. Redistributions in binary form must reproduce the above copyright notice,
15+
* this list of conditions and the following disclaimer in the documentation
16+
* and/or other materials provided with the distribution.
17+
*
18+
* 3. Neither the name of Analog Devices, Inc. nor the names of its
19+
* contributors may be used to endorse or promote products derived from this
20+
* software without specific prior written permission.
21+
*
22+
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
23+
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24+
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
25+
* EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
26+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28+
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29+
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30+
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
31+
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
*******************************************************************************/
33+
34+
#ifndef MAXIM_CAPI_TRNG_H_
35+
#define MAXIM_CAPI_TRNG_H_
36+
37+
#include "capi_trng.h"
38+
#include "capi_irq.h"
39+
40+
struct max_capi_trng_priv {
41+
/** Callback function for async */
42+
capi_trng_callback_t callback;
43+
/** Callback argument for async */
44+
void *callback_arg;
45+
};
46+
47+
extern const struct capi_trng_ops max_capi_trng_ops;
48+
49+
#endif /* MAXIM_CAPI_TRNG_H_ */

0 commit comments

Comments
 (0)