]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/T-HEAD_CB2201_CDK/csi/csi_driver/csky/common/trng/osr_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 / osr_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     osr_trng.c
19  * @brief    CSI Source File for TRNG Driver
20  * @version  V1.0
21  * @date     02. June 2017
22  ******************************************************************************/
23
24 #include <stdbool.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include "drv_trng.h"
28 #include "osr_trng.h"
29
30
31 #define ERR_TRNG(errno) (CSI_DRV_ERRNO_TRNG_BASE | errno)
32 #define TRNG_NULL_PARAM_CHK(para)                         \
33         do {                                        \
34             if (para == NULL) {                     \
35                 return ERR_TRNG(EDRV_PARAMETER);   \
36             }                                       \
37         } while (0)
38
39 typedef struct {
40     uint32_t base;
41     uint32_t irq;
42     trng_event_cb_t cb;
43     trng_status_t status;
44 } osr_trng_priv_t;
45
46 extern int32_t target_get_trng(int32_t idx, uint32_t *base, uint32_t *irq);
47
48 static osr_trng_priv_t trng_handle[CONFIG_TRNG_NUM];
49
50 /* Driver Capabilities */
51 static const trng_capabilities_t driver_capabilities = {
52     .lowper_mode = 0 /* low power mode */
53 };
54
55 //
56 // Functions
57 //
58
59 osr_trng_reg_t *trng_reg = NULL;
60
61 static int32_t trng_disable_irq(void)
62 {
63     trng_reg->RBG_CR &= ~TRNG_IRQ_BIT;
64     return 0;
65 }
66
67 static int32_t trng_enable(void)
68 {
69     trng_reg->RBG_CR |= TRNG_EN;
70     return 0;
71 }
72
73 static int32_t trng_get_data(void)
74 {
75     int data = trng_reg->RBG_DR;
76     return data;
77 }
78
79 static int32_t trng_data_is_ready(void)
80 {
81     int flag = (trng_reg->RBG_FIFO_SR & TRNG_DATA_READY);
82     return flag;
83 }
84
85 /**
86   \brief       Initialize TRNG Interface. 1. Initializes the resources needed for the TRNG interface 2.registers event callback function
87   \param[in]   idx device id
88   \param[in]   cb_event  Pointer to \ref trng_event_cb_t
89   \return      pointer to trng handle
90 */
91 trng_handle_t csi_trng_initialize(int32_t idx, trng_event_cb_t cb_event)
92 {
93
94     if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
95         return NULL;
96     }
97
98     /* obtain the trng information */
99     uint32_t base = 0u;
100     uint32_t irq = 0u;
101     int32_t real_idx = target_get_trng(idx, &base, &irq);
102
103     if (real_idx != idx) {
104         return NULL;
105     }
106
107     osr_trng_priv_t *trng_priv = &trng_handle[idx];
108     trng_priv->base = base;
109     trng_priv->irq = irq;
110
111     /* initialize the trng context */
112     trng_reg = (osr_trng_reg_t *)(trng_priv->base);
113     trng_priv->cb = cb_event;
114     trng_priv->status.busy = 0;
115     trng_priv->status.data_valid = 0;
116
117     trng_disable_irq();
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     osr_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]   idx device id.
140   \return      \ref trng_capabilities_t
141 */
142 //trng_capabilities_t csi_trng_get_capabilities(int32_t idx)
143 trng_capabilities_t csi_trng_get_capabilities(trng_handle_t handle)
144 {
145     /*
146     if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
147         trng_capabilities_t ret;
148         memset(&ret, 0, sizeof(trng_capabilities_t));
149         return ret;
150     }*/
151     return driver_capabilities;
152 }
153
154 /**
155   \brief       Get data from the TRNG.
156   \param[in]   handle  trng handle to operate.
157   \param[out]  data  Pointer to buffer with data get from TRNG
158   \param[in]   num   Number of data items to obtain
159   \return      error code
160 */
161 int32_t csi_trng_get_data(trng_handle_t handle, void *data, uint32_t num)
162 {
163     TRNG_NULL_PARAM_CHK(handle);
164     TRNG_NULL_PARAM_CHK(data);
165     TRNG_NULL_PARAM_CHK(num);
166
167     osr_trng_priv_t *trng_priv = handle;
168
169     trng_priv->status.busy = 1U;
170     trng_priv->status.data_valid = 0U;
171
172     uint8_t left_len = (uint32_t)data & 0x3;
173     uint32_t result = 0;
174
175     trng_enable();
176     /* if the data addr is not aligned by word */
177     if (left_len) {
178         while (!trng_data_is_ready());
179         result = trng_get_data();
180
181         if (num > (4 - left_len)) {
182             memcpy(data, &result, 4 - left_len);
183         } else {
184             memcpy(data, &result, num);
185             trng_priv->status.busy = 0U;
186             trng_priv->status.data_valid = 1U;
187
188             if (trng_priv->cb) {
189                 //trng_priv->cb(0, TRNG_EVENT_DATA_GENERATE_COMPLETE);
190                 trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
191             }
192             return 0;
193         }
194         num -= (4 - left_len);
195         data += (4 - left_len);
196     }
197
198     uint32_t word_len = num >> 2;
199     left_len = num & 0x3;
200
201     /* obtain the data by word */
202     while (word_len--) {
203         while (!trng_data_is_ready());
204         result = trng_get_data();
205         *(uint32_t *)data = result;
206         data = (void *)((uint32_t)data + 4);
207     }
208
209     /* if the num is not aligned by word */
210     if (left_len) {
211         while (!trng_data_is_ready());
212         result = trng_get_data();
213         memcpy(data, &result, left_len);
214     }
215
216     trng_priv->status.busy = 0U;
217     trng_priv->status.data_valid = 1U;
218
219     if (trng_priv->cb) {
220         //trng_priv->cb(0, TRNG_EVENT_DATA_GENERATE_COMPLETE);
221         trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
222     }
223
224     return 0;
225 }
226
227 /**
228   \brief       Get TRNG status.
229   \param[in]   handle  trng handle to operate.
230   \return      TRNG status \ref trng_status_t
231 */
232 trng_status_t csi_trng_get_status(trng_handle_t handle)
233 {
234     if (handle == NULL) {
235         trng_status_t ret;
236         memset(&ret, 0, sizeof(trng_status_t));
237         return ret;
238     }
239     osr_trng_priv_t *trng_priv = handle;
240     return trng_priv->status;
241 }