fgmac_dma.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fgmac_dma.c
  15. * Date: 2022-04-06 14:46:52
  16. * LastEditTime: 2022-04-06 14:46:58
  17. * Description:  This file is for
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. */
  23. /***************************** Include Files *********************************/
  24. #include <string.h>
  25. #include "fassert.h"
  26. #include "fkernel.h"
  27. #include "fcache.h"
  28. #include "fdebug.h"
  29. #include "fgmac.h"
  30. #include "fgmac_hw.h"
  31. /************************** Constant Definitions *****************************/
  32. #if defined(__aarch64__)
  33. #define FGMAC_DMA_IS_64_BIT_MEMORY(addr) (GENMASK_ULL(63, 32) & (uintptr)(addr))
  34. #else
  35. #define FGMAC_DMA_IS_64_BIT_MEMORY(addr) (FALSE)
  36. #endif
  37. /**************************** Type Definitions *******************************/
  38. /***************** Macros (Inline Functions) Definitions *********************/
  39. #define FGMAC_DEBUG_TAG "FGMAC-DMA"
  40. #define FGMAC_ERROR(format, ...) FT_DEBUG_PRINT_E(FGMAC_DEBUG_TAG, format, ##__VA_ARGS__)
  41. #define FGMAC_WARN(format, ...) FT_DEBUG_PRINT_W(FGMAC_DEBUG_TAG, format, ##__VA_ARGS__)
  42. #define FGMAC_INFO(format, ...) FT_DEBUG_PRINT_I(FGMAC_DEBUG_TAG, format, ##__VA_ARGS__)
  43. #define FGMAC_DEBUG(format, ...) FT_DEBUG_PRINT_D(FGMAC_DEBUG_TAG, format, ##__VA_ARGS__)
  44. /************************** Variable Definitions *****************************/
  45. /************************** Function Prototypes ******************************/
  46. /**
  47. * @name: FGmacSetupTxDescRing
  48. * @msg: 配置FGMAC的接收DMA描述符和缓冲区
  49. * @param {FGmac *}instance_p 驱动控制数据
  50. * {volatile FGmacDmaDesc *} rx_desc_tbl 接收DMA描述符表(数组)
  51. * {u8} *rx_buf 接收DMA缓冲区(数组,每一个描述符对应一个缓冲区)
  52. * {const fsize_t} rx_pre_buf_len 单个DMA缓冲区的字节数
  53. * {const fsize_t} rx_buf_num DMA描述符或者DMA缓存区的数目
  54. * @return {FError} RX DMA初始化的错误码信息,FGMAC_SUCCESS 表示RX DMA初始化成功,其它返回值表示RX DMA初始化失败
  55. * @note 传入的rx_desc_tbl和rx_buf必须为32位空间地址
  56. */
  57. FError FGmacSetupRxDescRing(FGmac *instance_p, volatile FGmacDmaDesc *rx_desc_tbl,
  58. u8 *rx_buf, const fsize_t rx_pre_buf_len, const fsize_t rx_buf_num)
  59. {
  60. FASSERT(instance_p && rx_desc_tbl && rx_buf);
  61. u32 i;
  62. volatile FGmacDmaDesc *cur_rx_desc;
  63. FGmacRingDescData *rx_ring_p = &instance_p->rx_ring;
  64. uintptr base_addr = instance_p->config.base_addr;
  65. void *desc_end = (void *)(rx_desc_tbl + rx_buf_num * sizeof(FGmacDmaDesc));
  66. void *buf_end = (void *)(rx_buf + rx_buf_num * rx_pre_buf_len);
  67. /* check if end address of descriptor or buffer is in 64 bit memory,
  68. if TRUE, return error because DMA register can only hold 32 bit memory address */
  69. if ((FGMAC_DMA_IS_64_BIT_MEMORY(desc_end)) || (FGMAC_DMA_IS_64_BIT_MEMORY(buf_end)))
  70. {
  71. FGMAC_ERROR("invalid rx descriptor memory %p or rx dma buf memory %p",
  72. desc_end, buf_end);
  73. return FGMAC_ERR_INVALID_DMA_MEM;
  74. }
  75. /* init rx dma ring data */
  76. memset(rx_ring_p, 0, sizeof(*rx_ring_p));
  77. rx_ring_p->desc_max_num = rx_buf_num; /* total num of rx desc and rx buf */
  78. rx_ring_p->desc_idx = 0; /* idx of rx desc */
  79. rx_ring_p->desc_buf_idx = 0; /* idx of rx buf */
  80. rx_ring_p->desc_buf_base = rx_buf; /* base addr of rx buf */
  81. /* init rx dma descriptor table */
  82. memset((void *)rx_desc_tbl, 0, sizeof(FGmacDmaDesc) * rx_buf_num);
  83. for (i = 0; i < rx_buf_num; i++)
  84. {
  85. cur_rx_desc = rx_desc_tbl + i;
  86. cur_rx_desc->status = FGMAC_DMA_RDES0_OWN;
  87. cur_rx_desc->ctrl = (FGMAC_DMA_RDES1_BUFFER1_SIZE_MASK & rx_pre_buf_len);
  88. FCacheDCacheInvalidateRange((uintptr)&rx_buf[i * rx_pre_buf_len], rx_pre_buf_len);
  89. cur_rx_desc->buf_addr = (u32)((uintptr)&rx_buf[i * rx_pre_buf_len]);
  90. if ((rx_buf_num - 1) == i)
  91. {
  92. cur_rx_desc->ctrl |= FGMAC_DMA_RDES1_END_RING;
  93. }
  94. }
  95. /* flush descriptor */
  96. instance_p->rx_desc = rx_desc_tbl;
  97. FCacheDCacheInvalidateRange((uintptr)instance_p->rx_desc, sizeof(FGmacDmaDesc) * rx_buf_num);
  98. FGMAC_WRITE_REG32(base_addr, FGMAC_DMA_RX_LIST_BASE_OFFSET, (u32)(uintptr)rx_desc_tbl);
  99. return FGMAC_SUCCESS;
  100. }
  101. /**
  102. * @name: FGmacSetupTxDescRing
  103. * @msg: 配置FGMAC的发送DMA描述符和缓冲区
  104. * @param {FGmac *}instance_p 驱动控制数据
  105. * {volatile FGmacDmaDesc *} tx_desc_tbl 发送DMA描述符表(数组)
  106. * {u8} *tx_buf 发送DMA缓冲区(数组,每一个描述符对应一个缓冲区)
  107. * {const fsize_t} tx_pre_buf_len 单个DMA缓冲区的字节数
  108. * {const fsize_t} tx_buf_num DMA描述符或者DMA缓存区的数目
  109. * @return {FError} TX DMA初始化的错误码信息,FGMAC_SUCCESS 表示TX DMA初始化成功,其它返回值表示TX DMA初始化失败
  110. * @note 传入的tx_desc_tbl和tx_buf必须为32位空间地址
  111. */
  112. FError FGmacSetupTxDescRing(FGmac *instance_p, volatile FGmacDmaDesc *tx_desc_tbl,
  113. u8 *tx_buf, const fsize_t tx_pre_buf_len, const fsize_t tx_buf_num)
  114. {
  115. FASSERT(instance_p && tx_desc_tbl && tx_buf);
  116. u32 i;
  117. volatile FGmacDmaDesc *cur_tx_desc;
  118. FGmacRingDescData *tx_ring_p = &instance_p->tx_ring;
  119. uintptr base_addr = instance_p->config.base_addr;
  120. void *desc_end = (void *)(tx_desc_tbl + tx_buf_num * sizeof(FGmacDmaDesc));
  121. void *buf_end = (void *)(tx_buf + tx_buf_num * tx_pre_buf_len);
  122. /* check if end address of descriptor or buffer is in 64 bit memory,
  123. if TRUE, return error because DMA register can only hold 32 bit memory address */
  124. if ((FGMAC_DMA_IS_64_BIT_MEMORY(desc_end)) || (FGMAC_DMA_IS_64_BIT_MEMORY(buf_end)))
  125. {
  126. FGMAC_ERROR("invalid rx descriptor memory %p or rx dma buf memory %p",
  127. desc_end, buf_end);
  128. return FGMAC_ERR_INVALID_DMA_MEM;
  129. }
  130. /* setup DMA descriptor ring data */
  131. memset(tx_ring_p, 0, sizeof(*tx_ring_p));
  132. tx_ring_p->desc_max_num = tx_buf_num;
  133. tx_ring_p->desc_idx = 0;
  134. tx_ring_p->desc_buf_idx = 0;
  135. tx_ring_p->desc_buf_base = tx_buf;
  136. /* setup DMA descriptor */
  137. memset((void *)tx_desc_tbl, 0, tx_buf_num * sizeof(FGmacDmaDesc));
  138. tx_desc_tbl[tx_buf_num - 1].ctrl |= FGMAC_DMA_TDES1_END_RING;
  139. for (i = 0; i < tx_buf_num; i++)
  140. {
  141. cur_tx_desc = tx_desc_tbl + i;
  142. FCacheDCacheInvalidateRange((uintptr)&tx_buf[i * tx_pre_buf_len], tx_pre_buf_len);
  143. cur_tx_desc->buf_addr = (u32)((uintptr)&tx_buf[i * tx_pre_buf_len]);
  144. cur_tx_desc->status = 0;
  145. }
  146. /* flush descriptor */
  147. instance_p->tx_desc = tx_desc_tbl;
  148. FCacheDCacheInvalidateRange((uintptr)instance_p->tx_desc, tx_buf_num * sizeof(FGmacDmaDesc));
  149. FGMAC_WRITE_REG32(base_addr, FGMAC_DMA_TX_LIST_BASE_OFFSET, (u32)(uintptr)tx_desc_tbl);
  150. return FGMAC_SUCCESS;
  151. }
  152. /**
  153. * @name: FGmacStartTrans
  154. * @msg: 使能FGMAC DMA,使之可以接收/发送数据
  155. * @return {FError} FGMAC_SUCCESS 表示启动成功,其它返回值表示启动失败
  156. * @param {FGmac} *instance_p 驱动控制数据
  157. * @note 调用函数前需要确保FGMAC驱动初始化成功
  158. */
  159. FError FGmacStartTrans(FGmac *instance_p)
  160. {
  161. FASSERT(instance_p);
  162. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  163. {
  164. FGMAC_ERROR("device is already initialized!!!");
  165. return FGMAC_ERR_NOT_READY;
  166. }
  167. FGmacStartDmaTrans(instance_p->config.base_addr);
  168. return FGMAC_SUCCESS;
  169. }
  170. /**
  171. * @name: FGmacStopTrans
  172. * @msg: 去使能FGMAC DMA, 使之不再能接收/发送数据
  173. * @return {FError} FGMAC_SUCCESS 表示去启动成功,其它返回值表示去启动失败
  174. * @param {FGmac} *instance_p 驱动控制数据
  175. * @note 调用函数前需要确保FGMAC驱动初始化成功
  176. */
  177. FError FGmacStopTrans(FGmac *instance_p)
  178. {
  179. FASSERT(instance_p);
  180. if (FT_COMPONENT_IS_READY != instance_p->is_ready)
  181. {
  182. FGMAC_ERROR("device is already initialized!!!");
  183. return FGMAC_ERR_NOT_READY;
  184. }
  185. FGmacStopDmaTrans(instance_p->config.base_addr);
  186. return FGMAC_SUCCESS;
  187. }
  188. /**
  189. * @name: FGmacRecvFrame
  190. * @msg: 通过FGMAC接收数据帧
  191. * @return {FError} FGMAC_SUCCESS 表示接收数据帧成功,其它返回值表示接收数据帧失败
  192. * @param {FGmac} *instance_p 驱动控制数据
  193. * @note 调用函数前需要确保FGMAC驱动初始化成功
  194. */
  195. FError FGmacRecvFrame(FGmac *instance_p)
  196. {
  197. FASSERT(instance_p);
  198. FGmacRingDescData *rx_ring = &instance_p->rx_ring;
  199. volatile FGmacDmaDesc *cur_rx_desc = &instance_p->rx_desc[rx_ring->desc_idx];
  200. u32 desc_cnt = 0;
  201. u32 flag = (FGMAC_DMA_RDES0_FIRST_DESCRIPTOR | FGMAC_DMA_RDES0_LAST_DESCRIPTOR);
  202. while ((0 == (FGMAC_DMA_RDES0_OWN & cur_rx_desc->status)) &&
  203. (desc_cnt < rx_ring->desc_max_num))
  204. {
  205. desc_cnt++;
  206. if (FGMAC_DMA_RDES0_FIRST_DESCRIPTOR == (flag & cur_rx_desc->status))
  207. {
  208. rx_ring->desc_buf_idx = rx_ring->desc_idx;
  209. FGMAC_DMA_INC_DESC(rx_ring->desc_idx, rx_ring->desc_max_num);
  210. cur_rx_desc = &instance_p->rx_desc[rx_ring->desc_idx];
  211. }
  212. else if (0 == (flag & cur_rx_desc->status))
  213. {
  214. FGMAC_DMA_INC_DESC(rx_ring->desc_idx, rx_ring->desc_max_num);
  215. cur_rx_desc = &instance_p->rx_desc[rx_ring->desc_idx];
  216. }
  217. else
  218. {
  219. rx_ring->desc_buf_idx = rx_ring->desc_idx;
  220. FGMAC_DMA_INC_DESC(rx_ring->desc_idx, rx_ring->desc_max_num);
  221. return FGMAC_SUCCESS;
  222. }
  223. }
  224. return FGMAC_ERR_TRANS_FAILED;
  225. }
  226. /**
  227. * @name: FGmacSendFrame
  228. * @msg: 通过FGMAC发送数据帧
  229. * @return {FError} FGMAC_SUCCESS 表示发送数据帧成功,其它返回值表示发送数据帧失败
  230. * @param {FGmac} *instance_p 驱动控制数据
  231. * @param {u32} frame_len 数据帧长度
  232. * @note 调用函数前需要确保FGMAC驱动初始化成功
  233. */
  234. FError FGmacSendFrame(FGmac *instance_p, u32 frame_len)
  235. {
  236. FASSERT(instance_p);
  237. u32 size = 0U;
  238. u32 i = 0U;
  239. u32 buf_cnt = 0U;
  240. FError ret = FGMAC_SUCCESS;
  241. volatile FGmacDmaDesc *tx_desc;
  242. FGmacRingDescData *tx_ring = &instance_p->tx_ring;
  243. const u32 max_packet_size = instance_p->config.max_packet_size;
  244. if (0U == frame_len)
  245. {
  246. return FGMAC_SUCCESS;
  247. }
  248. if (max_packet_size < frame_len)
  249. {
  250. buf_cnt = frame_len / max_packet_size;
  251. if (frame_len % max_packet_size)
  252. buf_cnt++;
  253. }
  254. else
  255. {
  256. buf_cnt = 1U;
  257. }
  258. if (1U == buf_cnt)
  259. {
  260. tx_desc = &instance_p->tx_desc[tx_ring->desc_idx];
  261. /* Set LAST and FIRST segment */
  262. tx_desc->ctrl |= (FGMAC_DMA_TDES1_FIRST_SEGMENT | FGMAC_DMA_TDES1_LAST_SEGMENT);
  263. /* Set frame size */
  264. tx_desc->ctrl &= ~(FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
  265. tx_desc->ctrl |= (frame_len & FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
  266. /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
  267. tx_desc->status |= FGMAC_DMA_TDES0_OWN;
  268. FGMAC_DMA_INC_DESC(tx_ring->desc_idx, tx_ring->desc_max_num);
  269. }
  270. else
  271. {
  272. for (i = 0U; i < buf_cnt; i++)
  273. {
  274. tx_desc = &instance_p->tx_desc[tx_ring->desc_idx];
  275. /* Clear FIRST and LAST segment bits */
  276. tx_desc->ctrl &= ~(FGMAC_DMA_TDES1_FIRST_SEGMENT | FGMAC_DMA_TDES1_LAST_SEGMENT);
  277. if (0U == i)
  278. {
  279. tx_desc->ctrl |= FGMAC_DMA_TDES1_FIRST_SEGMENT; /* Setting the first segment bit */
  280. }
  281. /* Program size */
  282. tx_desc->ctrl &= ~(FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
  283. tx_desc->ctrl |= (max_packet_size & FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
  284. if ((buf_cnt - 1) == i)
  285. {
  286. /* Setting the last segment bit */
  287. tx_desc->ctrl |= FGMAC_DMA_TDES1_LAST_SEGMENT;
  288. size = frame_len - (buf_cnt - 1U) * max_packet_size;
  289. tx_desc->ctrl &= ~(FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
  290. tx_desc->ctrl |= (size & FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
  291. }
  292. /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
  293. tx_desc->status |= FGMAC_DMA_TDES0_OWN;
  294. FGMAC_DMA_INC_DESC(tx_ring->desc_idx, tx_ring->desc_max_num);
  295. }
  296. }
  297. FGmacResumeDmaSend(instance_p->config.base_addr);
  298. return ret;
  299. }