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