| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- /*
- * Copyright : (C) 2022 Phytium Information Technology, Inc.
- * All Rights Reserved.
- *
- * This program is OPEN SOURCE software: you can redistribute it and/or modify it
- * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
- * either version 1.0 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Phytium Public License for more details.
- *
- *
- * FilePath: fgmac_dma.c
- * Date: 2022-04-06 14:46:52
- * LastEditTime: 2022-04-06 14:46:58
- * Description: This file is for
- *
- * Modify History:
- * Ver Who Date Changes
- * ----- ------ -------- --------------------------------------
- */
- /***************************** Include Files *********************************/
- #include <string.h>
- #include "fassert.h"
- #include "fkernel.h"
- #include "fcache.h"
- #include "fdebug.h"
- #include "fgmac.h"
- #include "fgmac_hw.h"
- /************************** Constant Definitions *****************************/
- #if defined(__aarch64__)
- #define FGMAC_DMA_IS_64_BIT_MEMORY(addr) (GENMASK_ULL(63, 32) & (uintptr)(addr))
- #else
- #define FGMAC_DMA_IS_64_BIT_MEMORY(addr) (FALSE)
- #endif
- /**************************** Type Definitions *******************************/
- /***************** Macros (Inline Functions) Definitions *********************/
- #define FGMAC_DEBUG_TAG "FGMAC-DMA"
- #define FGMAC_ERROR(format, ...) FT_DEBUG_PRINT_E(FGMAC_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FGMAC_WARN(format, ...) FT_DEBUG_PRINT_W(FGMAC_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FGMAC_INFO(format, ...) FT_DEBUG_PRINT_I(FGMAC_DEBUG_TAG, format, ##__VA_ARGS__)
- #define FGMAC_DEBUG(format, ...) FT_DEBUG_PRINT_D(FGMAC_DEBUG_TAG, format, ##__VA_ARGS__)
- /************************** Variable Definitions *****************************/
- /************************** Function Prototypes ******************************/
- /**
- * @name: FGmacSetupTxDescRing
- * @msg: 配置FGMAC的接收DMA描述符和缓冲区
- * @param {FGmac *}instance_p 驱动控制数据
- * {volatile FGmacDmaDesc *} rx_desc_tbl 接收DMA描述符表(数组)
- * {u8} *rx_buf 接收DMA缓冲区(数组,每一个描述符对应一个缓冲区)
- * {const fsize_t} rx_pre_buf_len 单个DMA缓冲区的字节数
- * {const fsize_t} rx_buf_num DMA描述符或者DMA缓存区的数目
- * @return {FError} RX DMA初始化的错误码信息,FGMAC_SUCCESS 表示RX DMA初始化成功,其它返回值表示RX DMA初始化失败
- * @note 传入的rx_desc_tbl和rx_buf必须为32位空间地址
- */
- FError FGmacSetupRxDescRing(FGmac *instance_p, volatile FGmacDmaDesc *rx_desc_tbl,
- u8 *rx_buf, const fsize_t rx_pre_buf_len, const fsize_t rx_buf_num)
- {
- FASSERT(instance_p && rx_desc_tbl && rx_buf);
- u32 i;
- volatile FGmacDmaDesc *cur_rx_desc;
- FGmacRingDescData *rx_ring_p = &instance_p->rx_ring;
- uintptr base_addr = instance_p->config.base_addr;
- void *desc_end = (void *)(rx_desc_tbl + rx_buf_num * sizeof(FGmacDmaDesc));
- void *buf_end = (void *)(rx_buf + rx_buf_num * rx_pre_buf_len);
- /* check if end address of descriptor or buffer is in 64 bit memory,
- if TRUE, return error because DMA register can only hold 32 bit memory address */
- if ((FGMAC_DMA_IS_64_BIT_MEMORY(desc_end)) || (FGMAC_DMA_IS_64_BIT_MEMORY(buf_end)))
- {
- FGMAC_ERROR("invalid rx descriptor memory %p or rx dma buf memory %p",
- desc_end, buf_end);
- return FGMAC_ERR_INVALID_DMA_MEM;
- }
- /* init rx dma ring data */
- memset(rx_ring_p, 0, sizeof(*rx_ring_p));
- rx_ring_p->desc_max_num = rx_buf_num; /* total num of rx desc and rx buf */
- rx_ring_p->desc_idx = 0; /* idx of rx desc */
- rx_ring_p->desc_buf_idx = 0; /* idx of rx buf */
- rx_ring_p->desc_buf_base = rx_buf; /* base addr of rx buf */
- /* init rx dma descriptor table */
- memset((void *)rx_desc_tbl, 0, sizeof(FGmacDmaDesc) * rx_buf_num);
- for (i = 0; i < rx_buf_num; i++)
- {
- cur_rx_desc = rx_desc_tbl + i;
- cur_rx_desc->status = FGMAC_DMA_RDES0_OWN;
- cur_rx_desc->ctrl = (FGMAC_DMA_RDES1_BUFFER1_SIZE_MASK & rx_pre_buf_len);
- FCacheDCacheInvalidateRange((uintptr)&rx_buf[i * rx_pre_buf_len], rx_pre_buf_len);
- cur_rx_desc->buf_addr = (u32)((uintptr)&rx_buf[i * rx_pre_buf_len]);
- if ((rx_buf_num - 1) == i)
- {
- cur_rx_desc->ctrl |= FGMAC_DMA_RDES1_END_RING;
- }
- }
- /* flush descriptor */
- instance_p->rx_desc = rx_desc_tbl;
- FCacheDCacheInvalidateRange((uintptr)instance_p->rx_desc, sizeof(FGmacDmaDesc) * rx_buf_num);
- FGMAC_WRITE_REG32(base_addr, FGMAC_DMA_RX_LIST_BASE_OFFSET, (u32)(uintptr)rx_desc_tbl);
- return FGMAC_SUCCESS;
- }
- /**
- * @name: FGmacSetupTxDescRing
- * @msg: 配置FGMAC的发送DMA描述符和缓冲区
- * @param {FGmac *}instance_p 驱动控制数据
- * {volatile FGmacDmaDesc *} tx_desc_tbl 发送DMA描述符表(数组)
- * {u8} *tx_buf 发送DMA缓冲区(数组,每一个描述符对应一个缓冲区)
- * {const fsize_t} tx_pre_buf_len 单个DMA缓冲区的字节数
- * {const fsize_t} tx_buf_num DMA描述符或者DMA缓存区的数目
- * @return {FError} TX DMA初始化的错误码信息,FGMAC_SUCCESS 表示TX DMA初始化成功,其它返回值表示TX DMA初始化失败
- * @note 传入的tx_desc_tbl和tx_buf必须为32位空间地址
- */
- FError FGmacSetupTxDescRing(FGmac *instance_p, volatile FGmacDmaDesc *tx_desc_tbl,
- u8 *tx_buf, const fsize_t tx_pre_buf_len, const fsize_t tx_buf_num)
- {
- FASSERT(instance_p && tx_desc_tbl && tx_buf);
- u32 i;
- volatile FGmacDmaDesc *cur_tx_desc;
- FGmacRingDescData *tx_ring_p = &instance_p->tx_ring;
- uintptr base_addr = instance_p->config.base_addr;
- void *desc_end = (void *)(tx_desc_tbl + tx_buf_num * sizeof(FGmacDmaDesc));
- void *buf_end = (void *)(tx_buf + tx_buf_num * tx_pre_buf_len);
- /* check if end address of descriptor or buffer is in 64 bit memory,
- if TRUE, return error because DMA register can only hold 32 bit memory address */
- if ((FGMAC_DMA_IS_64_BIT_MEMORY(desc_end)) || (FGMAC_DMA_IS_64_BIT_MEMORY(buf_end)))
- {
- FGMAC_ERROR("invalid rx descriptor memory %p or rx dma buf memory %p",
- desc_end, buf_end);
- return FGMAC_ERR_INVALID_DMA_MEM;
- }
- /* setup DMA descriptor ring data */
- memset(tx_ring_p, 0, sizeof(*tx_ring_p));
- tx_ring_p->desc_max_num = tx_buf_num;
- tx_ring_p->desc_idx = 0;
- tx_ring_p->desc_buf_idx = 0;
- tx_ring_p->desc_buf_base = tx_buf;
- /* setup DMA descriptor */
- memset((void *)tx_desc_tbl, 0, tx_buf_num * sizeof(FGmacDmaDesc));
- tx_desc_tbl[tx_buf_num - 1].ctrl |= FGMAC_DMA_TDES1_END_RING;
- for (i = 0; i < tx_buf_num; i++)
- {
- cur_tx_desc = tx_desc_tbl + i;
- FCacheDCacheInvalidateRange((uintptr)&tx_buf[i * tx_pre_buf_len], tx_pre_buf_len);
- cur_tx_desc->buf_addr = (u32)((uintptr)&tx_buf[i * tx_pre_buf_len]);
- cur_tx_desc->status = 0;
- }
- /* flush descriptor */
- instance_p->tx_desc = tx_desc_tbl;
- FCacheDCacheInvalidateRange((uintptr)instance_p->tx_desc, tx_buf_num * sizeof(FGmacDmaDesc));
- FGMAC_WRITE_REG32(base_addr, FGMAC_DMA_TX_LIST_BASE_OFFSET, (u32)(uintptr)tx_desc_tbl);
- return FGMAC_SUCCESS;
- }
- /**
- * @name: FGmacStartTrans
- * @msg: 使能FGMAC DMA,使之可以接收/发送数据
- * @return {FError} FGMAC_SUCCESS 表示启动成功,其它返回值表示启动失败
- * @param {FGmac} *instance_p 驱动控制数据
- * @note 调用函数前需要确保FGMAC驱动初始化成功
- */
- FError FGmacStartTrans(FGmac *instance_p)
- {
- FASSERT(instance_p);
- if (FT_COMPONENT_IS_READY != instance_p->is_ready)
- {
- FGMAC_ERROR("device is already initialized!!!");
- return FGMAC_ERR_NOT_READY;
- }
- FGmacStartDmaTrans(instance_p->config.base_addr);
- return FGMAC_SUCCESS;
- }
- /**
- * @name: FGmacStopTrans
- * @msg: 去使能FGMAC DMA, 使之不再能接收/发送数据
- * @return {FError} FGMAC_SUCCESS 表示去启动成功,其它返回值表示去启动失败
- * @param {FGmac} *instance_p 驱动控制数据
- * @note 调用函数前需要确保FGMAC驱动初始化成功
- */
- FError FGmacStopTrans(FGmac *instance_p)
- {
- FASSERT(instance_p);
- if (FT_COMPONENT_IS_READY != instance_p->is_ready)
- {
- FGMAC_ERROR("device is already initialized!!!");
- return FGMAC_ERR_NOT_READY;
- }
- FGmacStopDmaTrans(instance_p->config.base_addr);
- return FGMAC_SUCCESS;
- }
- /**
- * @name: FGmacRecvFrame
- * @msg: 通过FGMAC接收数据帧
- * @return {FError} FGMAC_SUCCESS 表示接收数据帧成功,其它返回值表示接收数据帧失败
- * @param {FGmac} *instance_p 驱动控制数据
- * @note 调用函数前需要确保FGMAC驱动初始化成功
- */
- FError FGmacRecvFrame(FGmac *instance_p)
- {
- FASSERT(instance_p);
- FGmacRingDescData *rx_ring = &instance_p->rx_ring;
- volatile FGmacDmaDesc *cur_rx_desc = &instance_p->rx_desc[rx_ring->desc_idx];
- u32 desc_cnt = 0;
- u32 flag = (FGMAC_DMA_RDES0_FIRST_DESCRIPTOR | FGMAC_DMA_RDES0_LAST_DESCRIPTOR);
- while ((0 == (FGMAC_DMA_RDES0_OWN & cur_rx_desc->status)) &&
- (desc_cnt < rx_ring->desc_max_num))
- {
- desc_cnt++;
- if (FGMAC_DMA_RDES0_FIRST_DESCRIPTOR == (flag & cur_rx_desc->status))
- {
- rx_ring->desc_buf_idx = rx_ring->desc_idx;
- FGMAC_DMA_INC_DESC(rx_ring->desc_idx, rx_ring->desc_max_num);
- cur_rx_desc = &instance_p->rx_desc[rx_ring->desc_idx];
- }
- else if (0 == (flag & cur_rx_desc->status))
- {
- FGMAC_DMA_INC_DESC(rx_ring->desc_idx, rx_ring->desc_max_num);
- cur_rx_desc = &instance_p->rx_desc[rx_ring->desc_idx];
- }
- else
- {
- rx_ring->desc_buf_idx = rx_ring->desc_idx;
- FGMAC_DMA_INC_DESC(rx_ring->desc_idx, rx_ring->desc_max_num);
- return FGMAC_SUCCESS;
- }
- }
- return FGMAC_ERR_TRANS_FAILED;
- }
- /**
- * @name: FGmacSendFrame
- * @msg: 通过FGMAC发送数据帧
- * @return {FError} FGMAC_SUCCESS 表示发送数据帧成功,其它返回值表示发送数据帧失败
- * @param {FGmac} *instance_p 驱动控制数据
- * @param {u32} frame_len 数据帧长度
- * @note 调用函数前需要确保FGMAC驱动初始化成功
- */
- FError FGmacSendFrame(FGmac *instance_p, u32 frame_len)
- {
- FASSERT(instance_p);
- u32 size = 0U;
- u32 i = 0U;
- u32 buf_cnt = 0U;
- FError ret = FGMAC_SUCCESS;
- volatile FGmacDmaDesc *tx_desc;
- FGmacRingDescData *tx_ring = &instance_p->tx_ring;
- const u32 max_packet_size = instance_p->config.max_packet_size;
- if (0U == frame_len)
- {
- return FGMAC_SUCCESS;
- }
- if (max_packet_size < frame_len)
- {
- buf_cnt = frame_len / max_packet_size;
- if (frame_len % max_packet_size)
- buf_cnt++;
- }
- else
- {
- buf_cnt = 1U;
- }
- if (1U == buf_cnt)
- {
- tx_desc = &instance_p->tx_desc[tx_ring->desc_idx];
- /* Set LAST and FIRST segment */
- tx_desc->ctrl |= (FGMAC_DMA_TDES1_FIRST_SEGMENT | FGMAC_DMA_TDES1_LAST_SEGMENT);
- /* Set frame size */
- tx_desc->ctrl &= ~(FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
- tx_desc->ctrl |= (frame_len & FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
- /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
- tx_desc->status |= FGMAC_DMA_TDES0_OWN;
- FGMAC_DMA_INC_DESC(tx_ring->desc_idx, tx_ring->desc_max_num);
- }
- else
- {
- for (i = 0U; i < buf_cnt; i++)
- {
- tx_desc = &instance_p->tx_desc[tx_ring->desc_idx];
- /* Clear FIRST and LAST segment bits */
- tx_desc->ctrl &= ~(FGMAC_DMA_TDES1_FIRST_SEGMENT | FGMAC_DMA_TDES1_LAST_SEGMENT);
- if (0U == i)
- {
- tx_desc->ctrl |= FGMAC_DMA_TDES1_FIRST_SEGMENT; /* Setting the first segment bit */
- }
- /* Program size */
- tx_desc->ctrl &= ~(FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
- tx_desc->ctrl |= (max_packet_size & FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
- if ((buf_cnt - 1) == i)
- {
- /* Setting the last segment bit */
- tx_desc->ctrl |= FGMAC_DMA_TDES1_LAST_SEGMENT;
- size = frame_len - (buf_cnt - 1U) * max_packet_size;
- tx_desc->ctrl &= ~(FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
- tx_desc->ctrl |= (size & FGMAC_DMA_TDES1_BUFFER1_SIZE_MASK);
- }
- /* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
- tx_desc->status |= FGMAC_DMA_TDES0_OWN;
- FGMAC_DMA_INC_DESC(tx_ring->desc_idx, tx_ring->desc_max_num);
- }
- }
- FGmacResumeDmaSend(instance_p->config.base_addr);
- return ret;
- }
|