1 /**
2   *********************************************************************************
3   *
4   * @file    ald_trng.c
5   * @brief   TRNG module driver.
6   *
7   * @version V1.0
8   * @date    04 Dec 2017
9   * @author  AE Team
10   * @note
11   *
12   * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
13   *
14   * SPDX-License-Identifier: Apache-2.0
15   *
16   * Licensed under the Apache License, Version 2.0 (the License); you may
17   * not use this file except in compliance with the License.
18   * You may obtain a copy of the License at
19   *
20   * www.apache.org/licenses/LICENSE-2.0
21   *
22   * Unless required by applicable law or agreed to in writing, software
23   * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25   * See the License for the specific language governing permissions and
26   * limitations under the License.
27   *
28   *********************************************************************************
29   */
30 
31 #include "ald_trng.h"
32 
33 
34 /** @addtogroup ES32FXXX_ALD
35   * @{
36   */
37 
38 /** @defgroup TRNG TRNG
39   * @brief TRNG module driver
40   * @{
41   */
42 #ifdef ALD_TRNG
43 
44 /** @addtogroup CRYPT_Private_Functions CRYPT Private Functions
45   * @{
46   */
47 void trng_reset(trng_handle_t *hperh);
48 /**
49   * @}
50   */
51 
52 /** @defgroup TRNG_Public_Functions TRNG Public Functions
53   * @{
54   */
55 
56 /** @addtogroup TRNG_Public_Functions_Group1 Initialization functions
57   * @brief Initialization functions
58   *
59   * @verbatim
60   ==============================================================================
61               ##### Initialization functions #####
62   ==============================================================================
63     [..]  This section provides functions allowing to initialize the TRNG:
64       (+) This parameters can be configured:
65         (++) Word Width
66         (++) Seed Type
67         (++) Seed
68         (++) Start Time
69         (++) Adjust parameter
70 
71     @endverbatim
72   * @{
73   */
74 
75 
76 /**
77   * @brief  Initializes the TRNG according to the specified
78   *         parameters in the trng_init_t.
79   * @param  hperh: Pointer to a trng_handle_t structure that contains
80   *         the configuration information for the specified TRNG module.
81   * @retval Status, see @ref ald_status_t.
82   */
ald_trng_init(trng_handle_t * hperh)83 ald_status_t ald_trng_init(trng_handle_t *hperh)
84 {
85 	uint32_t tmp = 0;
86 
87 	if (hperh == NULL)
88 		return ERROR;
89 
90 	assert_param(IS_TRNG_DATA_WIDTH(hperh->init.data_width));
91 	assert_param(IS_TRNG_SEED_TYPE(hperh->init.seed_type));
92 	assert_param(IS_TRNG_ADJC(hperh->init.adjc));
93 	assert_param(IS_FUNC_STATE(hperh->init.posten));
94 	assert_param(IS_TRNG_T_START(hperh->init.t_start));
95 
96 	__LOCK(hperh);
97 	trng_reset(hperh);
98 
99 	if (hperh->state == TRNG_STATE_RESET)
100 		__UNLOCK(hperh);
101 
102 	tmp = TRNG->CR;
103 
104 	if (hperh->init.adjc == 0)
105 		tmp = (0 << TRNG_CR_ADJM_POS);
106 	else
107 		tmp = (1 << TRNG_CR_ADJM_POS);
108 
109 	tmp |= ((1 << TRNG_CR_TRNGSEL_POS) | (hperh->init.data_width << TRNG_CR_DSEL_POSS) |
110 	       (hperh->init.seed_type << TRNG_CR_SDSEL_POSS) | (hperh->init.adjc << TRNG_CR_ADJC_POSS) |
111 	       (hperh->init.posten << TRNG_CR_POSTEN_MSK));
112 
113 	TRNG->CR = tmp;
114 
115 	WRITE_REG(TRNG->SEED, hperh->init.seed);
116 	MODIFY_REG(TRNG->CFGR, TRNG_CFGR_TSTART_MSK, (hperh->init.t_start) << TRNG_CFGR_TSTART_POSS);
117 
118 	hperh->state = TRNG_STATE_READY;
119 	__UNLOCK(hperh);
120 	return OK;
121 }
122 /**
123   * @}
124   */
125 
126 /** @addtogroup TRNG_Public_Functions_Group2 Peripheral Control functions
127   * @brief Peripheral Control functions
128   *
129   * @verbatim
130   ==============================================================================
131               ##### Peripheral Control functions #####
132   ==============================================================================
133   [..]  This section provides functions allowing to:
134     (+) ald_trng_get_result() API can Get the result.
135     (+) ald_trng_interrupt_config() API can be helpful to configure TRNG interrupt source.
136     (+) ald_trng_get_it_status() API can get the status of interrupt source.
137     (+) ald_trng_get_status() API can get the status of SR register.
138     (+) ald_trng_get_flag_status() API can get the status of interrupt flag.
139     (+) ald_trng_clear_flag_status() API can clear interrupt flag.
140 
141     @endverbatim
142   * @{
143   */
144 
145 /**
146   * @brief  Get the result.
147   * @param  hperh: Pointer to a trng_handle_t structure that contains
148   *         the configuration information for the specified TRNG module.
149   * @retval The resultl
150   */
ald_trng_get_result(trng_handle_t * hperh)151 uint32_t ald_trng_get_result(trng_handle_t *hperh)
152 {
153 	hperh->state = TRNG_STATE_READY;
154 	hperh->data = hperh->perh->DR;
155 	return (uint32_t)hperh->perh->DR;
156 }
157 
158 /**
159   * @brief  Enable/disable the specified interrupts.
160   * @param  hperh: Pointer to a trng_handle_t structure that contains
161   *         the configuration information for the specified TRNG module.
162   * @param  it: Specifies the interrupt sources to be enabled or disabled.
163   *         This parameter can be one of the @ref trng_it_t.
164   * @param  state: New state of the specified interrupts.
165   *         This parameter can be:
166   *             @arg ENABLE
167   *             @arg DISABLE
168   * @retval None
169   */
ald_trng_interrupt_config(trng_handle_t * hperh,trng_it_t it,type_func_t state)170 void ald_trng_interrupt_config(trng_handle_t *hperh, trng_it_t it, type_func_t state)
171 {
172 	assert_param(IS_TRNG_IT(it));
173 	assert_param(IS_FUNC_STATE(state));
174 
175 	if (state)
176 		SET_BIT(hperh->perh->IER, it);
177 	else
178 		CLEAR_BIT(hperh->perh->IER, it);
179 
180 	return;
181 }
182 
183 /**
184   * @brief  Get the status of SR register.
185   * @param  hperh: Pointer to a trng_handle_t structure that contains
186   *         the configuration information for the specified TRNG module.
187   * @param  status: Specifies the TRNG status type.
188   *         This parameter can be one of the @ref trng_status_t.
189   * @retval Status:
190   *           - 0: RESET
191   *           - 1: SET
192   */
ald_trng_get_status(trng_handle_t * hperh,trng_status_t status)193 flag_status_t ald_trng_get_status(trng_handle_t *hperh, trng_status_t status)
194 {
195 	assert_param(IS_TRNG_STATUS(status));
196 
197 	if (READ_BIT(hperh->perh->SR, status))
198 		return SET;
199 
200 	return RESET;
201 }
202 
203 /**
204   * @brief  Get the status of interrupt source.
205   * @param  hperh: Pointer to a trng_handle_t structure that contains
206   *         the configuration information for the specified TRNG module.
207   * @param  it: Specifies the interrupt source.
208   *         This parameter can be one of the @ref trng_it_t.
209   * @retval Status:
210   *           - 0: RESET
211   *           - 1: SET
212   */
ald_trng_get_it_status(trng_handle_t * hperh,trng_it_t it)213 it_status_t ald_trng_get_it_status(trng_handle_t *hperh, trng_it_t it)
214 {
215 	assert_param(IS_TRNG_IT(it));
216 
217 	if (READ_BIT(hperh->perh->IER, it))
218 		return SET;
219 
220 	return RESET;
221 }
222 
223 /**
224   * @brief  Get the status of interrupt flag.
225   * @param  hperh: Pointer to a trng_handle_t structure that contains
226   *         the configuration information for the specified TRNG module.
227   * @param  flag: Specifies the interrupt flag.
228   *         This parameter can be one of the @ref trng_flag_t.
229   * @retval Status:
230   *           - 0: RESET
231   *           - 1: SET
232   */
ald_trng_get_flag_status(trng_handle_t * hperh,trng_flag_t flag)233 flag_status_t ald_trng_get_flag_status(trng_handle_t *hperh, trng_flag_t flag)
234 {
235 	assert_param(IS_TRNG_FLAG(flag));
236 
237 	if (READ_BIT(hperh->perh->IFR, flag))
238 		return SET;
239 
240 	return RESET;
241 }
242 
243 /**
244   * @brief  Clear the interrupt flag.
245   * @param  hperh: Pointer to a trng_handle_t structure that contains
246   *         the configuration information for the specified TRNG module.
247   * @param  flag: Specifies the interrupt flag.
248   *         This parameter can be one of the @ref trng_flag_t.
249   * @retval None
250   */
ald_trng_clear_flag_status(trng_handle_t * hperh,trng_flag_t flag)251 void ald_trng_clear_flag_status(trng_handle_t *hperh, trng_flag_t flag)
252 {
253 	assert_param(IS_TRNG_FLAG(flag));
254 	WRITE_REG(hperh->perh->IFCR, flag);
255 
256 	return;
257 }
258 
259 /**
260   * @brief  Reset the TRNG peripheral.
261   * @param  hperh: Pointer to a trng_handle_t structure that contains
262   *         the configuration information for the specified TRNG module.
263   * @retval None
264   */
trng_reset(trng_handle_t * hperh)265 void trng_reset(trng_handle_t *hperh)
266 {
267 	TRNG->CR = 0;
268 	TRNG->SEED = 0;
269 	TRNG->CFGR = 0x1FF0707;
270 	TRNG->IER = 0;
271 	TRNG->IFCR = 0xFFFFFFFF;
272 
273 	hperh->state = TRNG_STATE_READY;
274 	__UNLOCK(hperh);
275 	return;
276 }
277 
278 /**
279   * @brief  This function handles TRNG interrupt request.
280   * @param  hperh: Pointer to a trng_handle_t structure that contains
281   *         the configuration information for the specified TRNG module.
282   * @retval None
283   */
ald_trng_irq_handler(trng_handle_t * hperh)284 void ald_trng_irq_handler(trng_handle_t *hperh)
285 {
286 	if (ald_trng_get_flag_status(hperh, TRNG_IF_SERR) == SET) {
287 		hperh->state = TRNG_STATE_ERROR;
288 		ald_trng_clear_flag_status(hperh, TRNG_IF_SERR);
289 		if (hperh->err_cplt_cbk)
290 			hperh->err_cplt_cbk(hperh);
291 		return;
292 	}
293 
294 	if (ald_trng_get_flag_status(hperh, TRNG_IF_DAVLD) == SET) {
295 		hperh->data = hperh->perh->DR;
296 		hperh->state = TRNG_STATE_READY;
297 		ald_trng_clear_flag_status(hperh, TRNG_IF_DAVLD);
298 		if (hperh->trng_cplt_cbk)
299 			hperh->trng_cplt_cbk(hperh);
300 	}
301 
302 	if (ald_trng_get_flag_status(hperh, TRNG_IF_START) == SET) {
303 		hperh->state = TRNG_STATE_BUSY;
304 		ald_trng_clear_flag_status(hperh, TRNG_IF_START);
305 		if (hperh->init_cplt_cbk)
306 			hperh->init_cplt_cbk(hperh);
307 	}
308 }
309 
310 /**
311   * @}
312   */
313 /**
314   * @}
315   */
316 #endif /* ALD_TRNG */
317 /**
318   * @}
319   */
320 
321 /**
322   * @}
323   */
324