1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2017, 2019 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_rnga.h"
10
11 #if defined(FSL_FEATURE_SOC_RNG_COUNT) && FSL_FEATURE_SOC_RNG_COUNT
12
13 /*******************************************************************************
14 * Definitions
15 *******************************************************************************/
16
17 /* Component ID definition, used by tools. */
18 #ifndef FSL_COMPONENT_ID
19 #define FSL_COMPONENT_ID "platform.drivers.rnga"
20 #endif
21
22 /*******************************************************************************
23 * RNG_CR - RNGA Control Register
24 ******************************************************************************/
25 /*!
26 * @brief RNG_CR - RNGA Control Register (RW)
27 *
28 * Reset value: 0x00000000U
29 *
30 * Controls the operation of RNGA.
31 */
32 /*!
33 * @name Constants and macros for entire RNG_CR register
34 */
35 /*@{*/
36 #define RNG_CR_REG(base) ((base)->CR)
37 #define RNG_RD_CR(base) (RNG_CR_REG(base))
38 #define RNG_WR_CR(base, value) (RNG_CR_REG(base) = (value))
39 #define RNG_RMW_CR(base, mask, value) (RNG_WR_CR(base, (RNG_RD_CR(base) & ~(mask)) | (value)))
40 /*@}*/
41
42 /*!
43 * @name Register RNG_CR, field GO[0] (RW)
44 *
45 * Specifies whether random-data generation and loading (into OR[RANDOUT]) is
46 * enabled.This field is sticky. You must reset RNGA to stop RNGA from loading
47 * OR[RANDOUT] with data.
48 *
49 * Values:
50 * - 0b0 - Disabled
51 * - 0b1 - Enabled
52 */
53 /*@{*/
54 /*! @brief Read current value of the RNG_CR_GO field. */
55 #define RNG_RD_CR_GO(base) ((RNG_CR_REG(base) & RNG_CR_GO_MASK) >> RNG_CR_GO_SHIFT)
56
57 /*! @brief Set the GO field to a new value. */
58 #define RNG_WR_CR_GO(base, value) (RNG_RMW_CR(base, RNG_CR_GO_MASK, RNG_CR_GO(value)))
59 /*@}*/
60
61 /*!
62 * @name Register RNG_CR, field SLP[4] (RW)
63 *
64 * Specifies whether RNGA is in Sleep or Normal mode. You can also enter Sleep
65 * mode by asserting the DOZE signal.
66 *
67 * Values:
68 * - 0b0 - Normal mode
69 * - 0b1 - Sleep (low-power) mode
70 */
71 /*@{*/
72 /*! @brief Read current value of the RNG_CR_SLP field. */
73 #define RNG_RD_CR_SLP(base) ((RNG_CR_REG(base) & RNG_CR_SLP_MASK) >> RNG_CR_SLP_SHIFT)
74
75 /*! @brief Set the SLP field to a new value. */
76 #define RNG_WR_CR_SLP(base, value) (RNG_RMW_CR(base, RNG_CR_SLP_MASK, RNG_CR_SLP(value)))
77 /*@}*/
78
79 /*******************************************************************************
80 * RNG_SR - RNGA Status Register
81 ******************************************************************************/
82 #define RNG_SR_REG(base) ((base)->SR)
83
84 /*!
85 * @name Register RNG_SR, field OREG_LVL[15:8] (RO)
86 *
87 * Indicates the number of random-data words that are in OR[RANDOUT], which
88 * indicates whether OR[RANDOUT] is valid.If you read OR[RANDOUT] when SR[OREG_LVL]
89 * is not 0, then the contents of a random number contained in OR[RANDOUT] are
90 * returned, and RNGA writes 0 to both OR[RANDOUT] and SR[OREG_LVL].
91 *
92 * Values:
93 * - 0b00000000 - No words (empty)
94 * - 0b00000001 - One word (valid)
95 */
96 /*@{*/
97 /*! @brief Read current value of the RNG_SR_OREG_LVL field. */
98 #define RNG_RD_SR_OREG_LVL(base) ((RNG_SR_REG(base) & RNG_SR_OREG_LVL_MASK) >> RNG_SR_OREG_LVL_SHIFT)
99 /*@}*/
100
101 /*!
102 * @name Register RNG_SR, field SLP[4] (RO)
103 *
104 * Specifies whether RNGA is in Sleep or Normal mode. You can also enter Sleep
105 * mode by asserting the DOZE signal.
106 *
107 * Values:
108 * - 0b0 - Normal mode
109 * - 0b1 - Sleep (low-power) mode
110 */
111 /*@{*/
112 /*! @brief Read current value of the RNG_SR_SLP field. */
113 #define RNG_RD_SR_SLP(base) ((RNG_SR_REG(base) & RNG_SR_SLP_MASK) >> RNG_SR_SLP_SHIFT)
114 /*@}*/
115
116 /*******************************************************************************
117 * RNG_OR - RNGA Output Register
118 ******************************************************************************/
119 /*!
120 * @brief RNG_OR - RNGA Output Register (RO)
121 *
122 * Reset value: 0x00000000U
123 *
124 * Stores a random-data word generated by RNGA.
125 */
126 /*!
127 * @name Constants and macros for entire RNG_OR register
128 */
129 /*@{*/
130 #define RNG_OR_REG(base) ((base)->OR)
131 #define RNG_RD_OR(base) (RNG_OR_REG(base))
132 /*@}*/
133
134 /*******************************************************************************
135 * RNG_ER - RNGA Entropy Register
136 ******************************************************************************/
137 /*!
138 * @brief RNG_ER - RNGA Entropy Register (WORZ)
139 *
140 * Reset value: 0x00000000U
141 *
142 * Specifies an entropy value that RNGA uses in addition to its ring oscillators
143 * to seed its pseudorandom algorithm. This is a write-only register; reads
144 * return all zeros.
145 */
146 /*!
147 * @name Constants and macros for entire RNG_ER register
148 */
149 /*@{*/
150 #define RNG_ER_REG(base) ((base)->ER)
151 #define RNG_RD_ER(base) (RNG_ER_REG(base))
152 #define RNG_WR_ER(base, value) (RNG_ER_REG(base) = (value))
153 /*@}*/
154
155 /*******************************************************************************
156 * Prototypes
157 *******************************************************************************/
158
159 static uint32_t rnga_ReadEntropy(RNG_Type *base);
160
161 /*******************************************************************************
162 * Code
163 ******************************************************************************/
164
165 /*!
166 * brief Initializes the RNGA.
167 *
168 * This function initializes the RNGA.
169 * When called, the RNGA entropy generation starts immediately.
170 *
171 * param base RNGA base address
172 */
RNGA_Init(RNG_Type * base)173 void RNGA_Init(RNG_Type *base)
174 {
175 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
176 /* Enable the clock gate. */
177 CLOCK_EnableClock(kCLOCK_Rnga0);
178 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
179 CLOCK_DisableClock(kCLOCK_Rnga0); /* To solve the release version on twrkm43z75m */
180 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
181 CLOCK_EnableClock(kCLOCK_Rnga0);
182 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
183
184 /* Reset the registers for RNGA module to reset state. */
185 RNG_WR_CR(base, 0);
186 /* Enables the RNGA random data generation and loading.*/
187 RNG_WR_CR_GO(base, 1);
188 }
189
190 /*!
191 * brief Shuts down the RNGA.
192 *
193 * This function shuts down the RNGA.
194 *
195 * param base RNGA base address
196 */
RNGA_Deinit(RNG_Type * base)197 void RNGA_Deinit(RNG_Type *base)
198 {
199 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
200 /* Disable the clock for RNGA module.*/
201 CLOCK_DisableClock(kCLOCK_Rnga0);
202 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
203 }
204
205 /*!
206 * @brief Get a random data from RNGA.
207 *
208 * @param base RNGA base address
209 */
rnga_ReadEntropy(RNG_Type * base)210 static uint32_t rnga_ReadEntropy(RNG_Type *base)
211 {
212 uint32_t data = 0;
213 if (RNGA_GetMode(base) == kRNGA_ModeNormal) /* Is in normal mode.*/
214 {
215 /* Wait for valid random-data.*/
216 while (RNG_RD_SR_OREG_LVL(base) == 0U)
217 {
218 }
219 data = RNG_RD_OR(base);
220 }
221 /* Get random-data word generated by RNGA.*/
222 return data;
223 }
224
225 /*!
226 * brief Gets random data.
227 *
228 * This function gets random data from the RNGA.
229 *
230 * param base RNGA base address
231 * param data pointer to user buffer to be filled by random data
232 * param data_size size of data in bytes
233 * return RNGA status
234 */
RNGA_GetRandomData(RNG_Type * base,void * data,size_t data_size)235 status_t RNGA_GetRandomData(RNG_Type *base, void *data, size_t data_size)
236 {
237 status_t result = kStatus_Success;
238 uint32_t random_32;
239 uint8_t *random_p;
240 uint32_t random_size;
241 uint8_t *data_p = (uint8_t *)data;
242 uint32_t i;
243
244 /* Check input parameters.*/
245 if ((NULL != base) && (NULL != data) && (0U != data_size))
246 {
247 do
248 {
249 /* Read Entropy.*/
250 random_32 = rnga_ReadEntropy(base);
251
252 random_p = (uint8_t *)&random_32;
253
254 if (data_size < sizeof(random_32))
255 {
256 random_size = data_size;
257 }
258 else
259 {
260 random_size = sizeof(random_32);
261 }
262
263 for (i = 0; i < random_size; i++)
264 {
265 *data_p++ = *random_p++;
266 }
267
268 data_size -= random_size;
269 } while (data_size > 0U);
270 }
271 else
272 {
273 result = kStatus_InvalidArgument;
274 }
275
276 return result;
277 }
278
279 /*!
280 * brief Sets the RNGA in normal mode or sleep mode.
281 *
282 * This function sets the RNGA in sleep mode or normal mode.
283 *
284 * param base RNGA base address
285 * param mode normal mode or sleep mode
286 */
RNGA_SetMode(RNG_Type * base,rnga_mode_t mode)287 void RNGA_SetMode(RNG_Type *base, rnga_mode_t mode)
288 {
289 RNG_WR_CR_SLP(base, (uint32_t)mode);
290 }
291
292 /*!
293 * brief Gets the RNGA working mode.
294 *
295 * This function gets the RNGA working mode.
296 *
297 * param base RNGA base address
298 * return normal mode or sleep mode
299 */
RNGA_GetMode(RNG_Type * base)300 rnga_mode_t RNGA_GetMode(RNG_Type *base)
301 {
302 return (rnga_mode_t)((uint32_t)(RNG_RD_SR_SLP(base)));
303 }
304
305 /*!
306 * brief Feeds the RNGA module.
307 *
308 * This function inputs an entropy value that the RNGA uses to seed its
309 * pseudo-random algorithm.
310 *
311 * param base RNGA base address
312 * param seed input seed value
313 */
RNGA_Seed(RNG_Type * base,uint32_t seed)314 void RNGA_Seed(RNG_Type *base, uint32_t seed)
315 {
316 /* Write to RNGA Entropy Register.*/
317 RNG_WR_ER(base, seed);
318 }
319
320 #endif /* FSL_FEATURE_SOC_RNG_COUNT */
321