]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/trng/ck_trng.c
Introduce a port for T-HEAD CK802. A simple demo for T-HEAD CB2201 is also included.
[freertos] / FreeRTOS / Demo / T-HEAD_CB2201_CDK / csi / csi_driver / csky / common / trng / ck_trng.c
1 /*
2  * Copyright (C) 2017 C-SKY Microsystems Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /******************************************************************************
18  * @file     ck_trng.c
19  * @brief    CSI Source File for TRNG Driver
20  * @version  V1.0
21  * @date     02. June 2017
22  ******************************************************************************/
23 #include <stdbool.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include "drv_trng.h"
27 #include "ck_trng.h"
28
29
30 #define ERR_TRNG(errno) (CSI_DRV_ERRNO_TRNG_BASE | errno)
31 #define TRNG_NULL_PARAM_CHK(para)                         \
32         do {                                        \
33             if (para == NULL) {                     \
34                 return ERR_TRNG(EDRV_PARAMETER);   \
35             }                                       \
36         } while (0)
37
38 typedef struct {
39     uint32_t base;
40     trng_event_cb_t cb;
41     trng_status_t status;
42 } ck_trng_priv_t;
43
44 extern int32_t target_get_trng_count(void);
45 extern int32_t target_get_trng(int32_t idx, uint32_t *base);
46
47 static ck_trng_priv_t trng_handle[CONFIG_TRNG_NUM];
48
49 /* Driver Capabilities */
50 static const trng_capabilities_t driver_capabilities = {
51     .lowper_mode = 1 /* low power mode */
52 };
53
54 extern int32_t target_get_trng(int32_t idx, uint32_t *base);
55 extern int32_t target_get_trng_count(void);
56 //
57 // Functions
58 //
59
60 ck_trng_reg_t *trng_reg = NULL;
61
62 static int32_t trng_enable(void)
63 {
64     trng_reg->TCR |= TRNG_EN;
65     return 0;
66 }
67
68 static int32_t trng_get_data(void)
69 {
70     int data = trng_reg->TDR;
71     return data;
72 }
73
74 static int32_t trng_data_is_ready(void)
75 {
76     int flag = (trng_reg->TCR & TRNG_DATA_READY);
77     return flag;
78 }
79
80 /**
81   \brief       get trng handle count.
82   \return      trng handle count
83 */
84 int32_t csi_trng_get_instance_count(void)
85 {
86     return target_get_trng_count();
87 }
88
89 /**
90   \brief       Initialize TRNG Interface. 1. Initializes the resources needed for the TRNG interface 2.registers event callback function
91   \param[in]   idx  must not exceed return value of csi_trng_get_instance_count()
92   \param[in]   cb_event  Pointer to \ref trng_event_cb_t
93   \return      pointer to trng handle
94 */
95 trng_handle_t csi_trng_initialize(int32_t idx, trng_event_cb_t cb_event)
96 {
97
98     if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
99         return NULL;
100     }
101
102     /* obtain the trng information */
103     uint32_t base = 0u;
104     int32_t real_idx = target_get_trng(idx, &base);
105
106     if (real_idx != idx) {
107         return NULL;
108     }
109
110     ck_trng_priv_t *trng_priv = &trng_handle[idx];
111     trng_priv->base = base;
112
113     /* initialize the trng context */
114     trng_reg = (ck_trng_reg_t *)(trng_priv->base);
115     trng_priv->cb = cb_event;
116     trng_priv->status.busy = 0;
117     trng_priv->status.data_valid = 0;
118
119     return (trng_handle_t)trng_priv;
120 }
121
122 /**
123   \brief       De-initialize TRNG Interface. stops operation and releases the software resources used by the interface
124   \param[in]   handle  trng handle to operate.
125   \return      error code
126 */
127 int32_t csi_trng_uninitialize(trng_handle_t handle)
128 {
129     TRNG_NULL_PARAM_CHK(handle);
130
131     ck_trng_priv_t *trng_priv = handle;
132     trng_priv->cb = NULL;
133
134     return 0;
135 }
136
137 /**
138   \brief       Get driver capabilities.
139   \param[in]   trng handle to operate.
140   \return      \ref trng_capabilities_t
141 */
142 trng_capabilities_t csi_trng_get_capabilities(trng_handle_t handle)
143 {
144     return driver_capabilities;
145 }
146
147 /**
148   \brief       Get data from the TRNG.
149   \param[in]   handle  trng handle to operate.
150   \param[out]  data  Pointer to buffer with data get from TRNG
151   \param[in]   num   Number of data items to obtain
152   \return      error code
153 */
154 int32_t csi_trng_get_data(trng_handle_t handle, void *data, uint32_t num)
155 {
156     TRNG_NULL_PARAM_CHK(handle);
157     TRNG_NULL_PARAM_CHK(data);
158     TRNG_NULL_PARAM_CHK(num);
159
160     ck_trng_priv_t *trng_priv = handle;
161
162     trng_priv->status.busy = 1U;
163     trng_priv->status.data_valid = 0U;
164
165     uint8_t left_len = (uint32_t)data & 0x3;
166     uint32_t result = 0;
167
168     /* if the data addr is not aligned by word */
169     if (left_len) {
170         trng_enable();
171         while (!trng_data_is_ready());
172         result = trng_get_data();
173         /* wait the data is ready */
174         while (trng_data_is_ready());
175
176         if (num > (4 - left_len)) {
177             memcpy(data, &result, 4 - left_len);
178         } else {
179             memcpy(data, &result, num);
180             trng_priv->status.busy = 0U;
181             trng_priv->status.data_valid = 1U;
182
183             if (trng_priv->cb) {
184                 trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
185             }
186             return 0;
187         }
188         num -= (4 - left_len);
189         data += (4 - left_len);
190     }
191
192     uint32_t word_len = num >> 2;
193     left_len = num & 0x3;
194
195     /* obtain the data by word */
196     while (word_len--) {
197         trng_enable();
198         while (!trng_data_is_ready());
199         result = trng_get_data();
200         while (trng_data_is_ready());
201         *(uint32_t *)data = result;
202         data = (void *)((uint32_t)data + 4);
203     }
204
205     /* if the num is not aligned by word */
206     if (left_len) {
207         trng_enable();
208         while (!trng_data_is_ready());
209         result = trng_get_data();
210         while (trng_data_is_ready());
211         memcpy(data, &result, left_len);
212     }
213
214     trng_priv->status.busy = 0U;
215     trng_priv->status.data_valid = 1U;
216
217     if (trng_priv->cb) {
218         trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
219     }
220
221     return 0;
222 }
223
224 /**
225   \brief       Get TRNG status.
226   \param[in]   handle  trng handle to operate.
227   \return      TRNG status \ref trng_status_t
228 */
229 trng_status_t csi_trng_get_status(trng_handle_t handle)
230 {
231     ck_trng_priv_t *trng_priv = handle;
232     return trng_priv->status;
233 }