ck_trng.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. * @file ck_trng.c
  18. * @brief CSI Source File for TRNG Driver
  19. * @version V1.0
  20. * @date 02. June 2017
  21. ******************************************************************************/
  22. #include <stdbool.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "drv_trng.h"
  26. #include "ck_trng.h"
  27. #define ERR_TRNG(errno) (CSI_DRV_ERRNO_TRNG_BASE | errno)
  28. #define TRNG_NULL_PARAM_CHK(para) \
  29. do { \
  30. if (para == NULL) { \
  31. return ERR_TRNG(EDRV_PARAMETER); \
  32. } \
  33. } while (0)
  34. typedef struct {
  35. uint32_t base;
  36. trng_event_cb_t cb;
  37. trng_status_t status;
  38. } ck_trng_priv_t;
  39. static ck_trng_priv_t trng_handle[CONFIG_TRNG_NUM];
  40. /* Driver Capabilities */
  41. static const trng_capabilities_t driver_capabilities = {
  42. .lowper_mode = 1 /* low power mode */
  43. };
  44. //
  45. // Functions
  46. //
  47. ck_trng_reg_t *trng_reg = NULL;
  48. static int32_t trng_enable(void)
  49. {
  50. trng_reg->TCR |= TRNG_EN;
  51. return 0;
  52. }
  53. static int32_t trng_get_data(void)
  54. {
  55. int data = trng_reg->TDR;
  56. return data;
  57. }
  58. static int32_t trng_data_is_ready(void)
  59. {
  60. int flag = (trng_reg->TCR & TRNG_DATA_READY);
  61. return flag;
  62. }
  63. int32_t __attribute__((weak)) target_get_trng_count(void)
  64. {
  65. return 0;
  66. }
  67. int32_t __attribute__((weak)) target_get_trng(int32_t idx, uint32_t *base)
  68. {
  69. return NULL;
  70. }
  71. /**
  72. \brief get trng handle count.
  73. \return trng handle count
  74. */
  75. int32_t csi_trng_get_instance_count(void)
  76. {
  77. return target_get_trng_count();
  78. }
  79. /**
  80. \brief Initialize TRNG Interface. 1. Initializes the resources needed for the TRNG interface 2.registers event callback function
  81. \param[in] idx must not exceed return value of csi_trng_get_instance_count()
  82. \param[in] cb_event Pointer to \ref trng_event_cb_t
  83. \return pointer to trng handle
  84. */
  85. trng_handle_t csi_trng_initialize(int32_t idx, trng_event_cb_t cb_event)
  86. {
  87. if (idx < 0 || idx >= CONFIG_TRNG_NUM) {
  88. return NULL;
  89. }
  90. /* obtain the trng information */
  91. uint32_t base = 0u;
  92. int32_t real_idx = target_get_trng(idx, &base);
  93. if (real_idx != idx) {
  94. return NULL;
  95. }
  96. ck_trng_priv_t *trng_priv = &trng_handle[idx];
  97. trng_priv->base = base;
  98. /* initialize the trng context */
  99. trng_reg = (ck_trng_reg_t *)(trng_priv->base);
  100. trng_priv->cb = cb_event;
  101. trng_priv->status.busy = 0;
  102. trng_priv->status.data_valid = 0;
  103. return (trng_handle_t)trng_priv;
  104. }
  105. /**
  106. \brief De-initialize TRNG Interface. stops operation and releases the software resources used by the interface
  107. \param[in] handle trng handle to operate.
  108. \return error code
  109. */
  110. int32_t csi_trng_uninitialize(trng_handle_t handle)
  111. {
  112. TRNG_NULL_PARAM_CHK(handle);
  113. ck_trng_priv_t *trng_priv = handle;
  114. trng_priv->cb = NULL;
  115. return 0;
  116. }
  117. /**
  118. \brief Get driver capabilities.
  119. \param[in] trng handle to operate.
  120. \return \ref trng_capabilities_t
  121. */
  122. trng_capabilities_t csi_trng_get_capabilities(trng_handle_t handle)
  123. {
  124. return driver_capabilities;
  125. }
  126. /**
  127. \brief Get data from the TRNG.
  128. \param[in] handle trng handle to operate.
  129. \param[out] data Pointer to buffer with data get from TRNG
  130. \param[in] num Number of data items to obtain
  131. \return error code
  132. */
  133. int32_t csi_trng_get_data(trng_handle_t handle, void *data, uint32_t num)
  134. {
  135. TRNG_NULL_PARAM_CHK(handle);
  136. TRNG_NULL_PARAM_CHK(data);
  137. TRNG_NULL_PARAM_CHK(num);
  138. ck_trng_priv_t *trng_priv = handle;
  139. trng_priv->status.busy = 1U;
  140. trng_priv->status.data_valid = 0U;
  141. uint8_t left_len = (uint32_t)data & 0x3;
  142. uint32_t result = 0;
  143. /* if the data addr is not aligned by word */
  144. if (left_len) {
  145. trng_enable();
  146. while (!trng_data_is_ready());
  147. result = trng_get_data();
  148. /* wait the data is ready */
  149. while (trng_data_is_ready());
  150. if (num > (4 - left_len)) {
  151. memcpy(data, &result, 4 - left_len);
  152. } else {
  153. memcpy(data, &result, num);
  154. trng_priv->status.busy = 0U;
  155. trng_priv->status.data_valid = 1U;
  156. if (trng_priv->cb) {
  157. trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
  158. }
  159. return 0;
  160. }
  161. num -= (4 - left_len);
  162. }
  163. uint32_t word_len = num >> 2;
  164. left_len = num & 0x3;
  165. /* obtain the data by word */
  166. while (word_len--) {
  167. trng_enable();
  168. while (!trng_data_is_ready());
  169. result = trng_get_data();
  170. while (trng_data_is_ready());
  171. *(uint32_t *)data = result;
  172. data += 4;
  173. }
  174. /* if the num is not aligned by word */
  175. if (left_len) {
  176. trng_enable();
  177. while (!trng_data_is_ready());
  178. result = trng_get_data();
  179. while (trng_data_is_ready());
  180. memcpy(data, &result, left_len);
  181. }
  182. trng_priv->status.busy = 0U;
  183. trng_priv->status.data_valid = 1U;
  184. if (trng_priv->cb) {
  185. trng_priv->cb(TRNG_EVENT_DATA_GENERATE_COMPLETE);
  186. }
  187. return 0;
  188. }
  189. /**
  190. \brief Get TRNG status.
  191. \param[in] handle trng handle to operate.
  192. \return TRNG status \ref trng_status_t
  193. */
  194. trng_status_t csi_trng_get_status(trng_handle_t handle)
  195. {
  196. ck_trng_priv_t *trng_priv = handle;
  197. return trng_priv->status;
  198. }