1 /*
2  * Copyright (c) 2016 ARM Limited.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_kinetis_rnga
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/entropy.h>
11 #include <zephyr/random/random.h>
12 #include <zephyr/init.h>
13 
14 #include "fsl_rnga.h"
15 
entropy_mcux_rnga_get_uint8(void)16 static uint8_t entropy_mcux_rnga_get_uint8(void)
17 {
18 	uint32_t random;
19 	uint8_t output = 0U;
20 	int i;
21 
22 	RNGA_SetMode(RNG, kRNGA_ModeNormal);
23 	/* The Reference manual states that back to back reads from
24 	 * the RNGA deliver one or two bits of entropy per 32-bit
25 	 * word, therefore to deliver 8 bits of entropy we need
26 	 * between 4 and 8 samples.  Conservatively, we take 8.
27 	 */
28 	for (i = 0; i < 8; i++) {
29 		status_t status;
30 
31 		status = RNGA_GetRandomData(RNG, &random, sizeof(random));
32 		__ASSERT_NO_MSG(!status);
33 		output ^= random;
34 	}
35 
36 	RNGA_SetMode(RNG, kRNGA_ModeSleep);
37 
38 	return output;
39 }
40 
entropy_mcux_rnga_get_entropy(const struct device * dev,uint8_t * buffer,uint16_t length)41 static int entropy_mcux_rnga_get_entropy(const struct device *dev,
42 					 uint8_t *buffer,
43 					 uint16_t length)
44 {
45 	int i;
46 
47 	ARG_UNUSED(dev);
48 
49 	for (i = 0; i < length; i++) {
50 		buffer[i] = entropy_mcux_rnga_get_uint8();
51 	}
52 
53 	return 0;
54 }
55 
56 static DEVICE_API(entropy, entropy_mcux_rnga_api_funcs) = {
57 	.get_entropy = entropy_mcux_rnga_get_entropy
58 };
59 
entropy_mcux_rnga_init(const struct device * dev)60 static int entropy_mcux_rnga_init(const struct device *dev)
61 {
62 	uint32_t seed = k_cycle_get_32();
63 
64 	ARG_UNUSED(dev);
65 
66 	RNGA_Init(RNG);
67 
68 	/* The range of seed values acquired by this method is likely
69 	 * to be relatively small.  The RNGA hardware uses two free
70 	 * running oscillators to add entropy to the seed value, we
71 	 * take care below to ensure the read rate is lower than the
72 	 * rate at which the hardware can add entropy.
73 	 */
74 	RNGA_Seed(RNG, seed);
75 	RNGA_SetMode(RNG, kRNGA_ModeSleep);
76 	return 0;
77 }
78 
79 DEVICE_DT_INST_DEFINE(0,
80 		    entropy_mcux_rnga_init, NULL, NULL, NULL,
81 		    PRE_KERNEL_1, CONFIG_ENTROPY_INIT_PRIORITY,
82 		    &entropy_mcux_rnga_api_funcs);
83