/**
  ******************************************************************************
  * @file    bl702_emac.c
  * @version V1.0
  * @date
  * @brief   This file is the standard driver c file
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of Bouffalo Lab nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */

#include "bl702.h"
#include "bl702_emac.h"
#include "bl702_glb.h"

/** @addtogroup  BL702_Peripheral_Driver
 *  @{
 */

/** @addtogroup  EMAC
 *  @{
 */

/** @defgroup  EMAC_Private_Macros
 *  @{
 */
#define PHY_MAX_RETRY (0x3F0)

/*@} end of group EMAC_Private_Macros */

/** @defgroup  EMAC_Private_Types
 *  @{
 */

/*@} end of group EMAC_Private_Types */

/** @defgroup  EMAC_Private_Variables
 *  @{
 */
static intCallback_Type *emacIntCbfArra[EMAC_INT_CNT] = { NULL };

/*@} end of group EMAC_Private_Variables */

/** @defgroup  EMAC_Global_Variables
 *  @{
 */

/*@} end of group EMAC_Global_Variables */

/** @defgroup  EMAC_Private_Fun_Declaration
 *  @{
 */

/*@} end of group EMAC_Private_Fun_Declaration */

/** @defgroup  EMAC_Private_Functions
 *  @{
 */

/****************************************************************************/ /**
 * @brief  Set MAC Address
 *
 * @param  macAddr[6]: MAC address buffer array
 *
 * @return None
 *
*******************************************************************************/
static void EMAC_SetMACAddress(uint8_t macAddr[6])
{
    BL_WR_REG(EMAC_BASE, EMAC_MAC_ADDR1, (macAddr[0] << 8) | macAddr[1]);
    BL_WR_REG(EMAC_BASE, EMAC_MAC_ADDR0, (macAddr[2] << 24) | (macAddr[3] << 16) | (macAddr[4] << 8) | (macAddr[5] << 0));
}

/****************************************************************************/ /**
 * @brief  Set PHY Address
 *
 * @param  phyAddress: Phy address
 *
 * @return None
 *
*******************************************************************************/
void EMAC_Phy_SetAddress(uint16_t phyAddress)
{
    uint32_t tmpVal;

    /* Set Phy Address */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MIIADDRESS);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_FIAD, phyAddress);
    BL_WR_REG(EMAC_BASE, EMAC_MIIADDRESS, tmpVal);
}

/****************************************************************************/ /**
 * @brief  Set PHY Address
 *
 * @param  phyAddress: Phy address
 *
 * @return None
 *
*******************************************************************************/
void EMAC_Phy_Set_Full_Duplex(uint8_t fullDuplex)
{
    uint32_t tmpVal;

    /* Set MAC duplex config */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MODE);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_FULLD, fullDuplex);
    BL_WR_REG(EMAC_BASE, EMAC_MODE, tmpVal);
}

/****************************************************************************/ /**
 * @brief  Read PHY register
 *
 * @param  phyReg: PHY register
 * @param  regValue: PHY register value pointer
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Phy_Read(uint16_t phyReg, uint16_t *regValue)
{
    uint32_t tmpVal;

    /* Set Register Address */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MIIADDRESS);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_RGAD, phyReg);
    BL_WR_REG(EMAC_BASE, EMAC_MIIADDRESS, tmpVal);

    /* Trigger read */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MIICOMMAND);
    tmpVal = BL_SET_REG_BIT(tmpVal, EMAC_RSTAT);
    BL_WR_REG(EMAC_BASE, EMAC_MIICOMMAND, tmpVal);

    BL_DRV_DUMMY;

    do {
        tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MIISTATUS);
        BL702_Delay_US(16);
    } while (BL_IS_REG_BIT_SET(tmpVal, EMAC_MIIM_BUSY));

    *regValue = BL_RD_REG(EMAC_BASE, EMAC_MIIRX_DATA);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  Write PHY register
 *
 * @param  phyReg: PHY register
 * @param  regValue: PHY register value
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Phy_Write(uint16_t phyReg, uint16_t regValue)
{
    uint32_t tmpVal;

    /* Set Register Address */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MIIADDRESS);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_RGAD, phyReg);
    BL_WR_REG(EMAC_BASE, EMAC_MIIADDRESS, tmpVal);

    /* Set Write data */
    BL_WR_REG(EMAC_BASE, EMAC_MIITX_DATA, regValue);

    /* Trigger write */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MIICOMMAND);
    tmpVal = BL_SET_REG_BIT(tmpVal, EMAC_WCTRLDATA);
    BL_WR_REG(EMAC_BASE, EMAC_MIICOMMAND, tmpVal);

    BL_DRV_DUMMY;

    do {
        tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MIISTATUS);
    } while (BL_IS_REG_BIT_SET(tmpVal, EMAC_MIIM_BUSY));

    return SUCCESS;
}

/*@} end of group EMAC_Private_Functions */

/** @defgroup  EMAC_Public_Functions
 *  @{
 */

/****************************************************************************/ /**
 * @brief  Initialize EMAC module
 *
 * @param  cfg: EMAC configuration pointer
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Init(EMAC_CFG_Type *cfg)
{
    uint32_t tmpVal;

    /* Disable clock gate */
    GLB_AHB_Slave1_Clock_Gate(DISABLE, BL_AHB_SLAVE1_EMAC);

    /* Set MAC config */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MODE);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_RMII_EN, 1);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_RECSMALL, cfg->recvSmallFrame);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_PAD, cfg->padEnable);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_HUGEN, cfg->recvHugeFrame);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_CRCEN, cfg->crcEnable);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_NOPRE, cfg->noPreamble);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_BRO, cfg->recvBroadCast);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_PRO, ENABLE);
    //tmpVal |= (1 << 7); /* local loopback in emac */
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_IFG, cfg->interFrameGapCheck);
    BL_WR_REG(EMAC_BASE, EMAC_MODE, tmpVal);

    /* Set inter frame gap value */
    BL_WR_REG(EMAC_BASE, EMAC_IPGT, cfg->interFrameGapValue);

    /* Set MII interface */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MIIMODE);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_MIINOPRE, cfg->miiNoPreamble);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_CLKDIV, cfg->miiClkDiv);
    BL_WR_REG(EMAC_BASE, EMAC_MIIMODE, tmpVal);

    /* Set collision */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_COLLCONFIG);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_MAXRET, cfg->maxTxRetry);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_COLLVALID, cfg->collisionValid);
    BL_WR_REG(EMAC_BASE, EMAC_COLLCONFIG, tmpVal);

    /* Set frame length */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_PACKETLEN);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_MINFL, cfg->minFrameLen);
    tmpVal = BL_SET_REG_BITS_VAL(tmpVal, EMAC_MAXFL, cfg->maxFrameLen);
    BL_WR_REG(EMAC_BASE, EMAC_PACKETLEN, tmpVal);

    EMAC_SetMACAddress(cfg->macAddr);

    void EMAC_IRQHandler(void);
    Interrupt_Handler_Register(EMAC_IRQn, EMAC_IRQHandler);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  DeInitialize EMAC module
 *
 * @param  None
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_DeInit(void)
{
    EMAC_Disable();

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  Initialize EMAC TX RX MDA buffer
 *
 * @param  handle: EMAC handle pointer
 * @param  txBuff: TX buffer
 * @param  txBuffCount: TX buffer count
 * @param  rxBuff: RX buffer
 * @param  rxBuffCount: RX buffer count
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_DMADescListInit(EMAC_Handle_Type *handle, uint8_t *txBuff, uint32_t txBuffCount, uint8_t *rxBuff, uint32_t rxBuffCount)
{
    uint32_t i = 0;

    /* Set the Ethernet handler env */
    handle->bd = (EMAC_BD_Desc_Type *)(EMAC_BASE + EMAC_DMA_DESC_OFFSET);
    handle->txIndexEMAC = 0;
    handle->txIndexCPU = 0;
    handle->txBuffLimit = txBuffCount - 1;
    /* The receive descriptors' address starts right after the last transmit BD. */
    handle->rxIndexEMAC = txBuffCount;
    handle->rxIndexCPU = txBuffCount;
    handle->rxBuffLimit = txBuffCount + rxBuffCount - 1;

    /* Fill each DMARxDesc descriptor with the right values */
    for (i = 0; i < txBuffCount; i++) {
        /* Get the pointer on the ith member of the Tx Desc list */
        handle->bd[i].Buffer = (NULL == txBuff) ? 0 : (uint32_t)(txBuff + (ETH_MAX_PACKET_SIZE * i));
        handle->bd[i].C_S_L = 0;
    }

    /* For the last TX DMA Descriptor, it should be wrap back */
    handle->bd[handle->txBuffLimit].C_S_L |= EMAC_BD_FIELD_MSK(TX_WR);

    for (i = txBuffCount; i < (txBuffCount + rxBuffCount); i++) {
        /* Get the pointer on the ith member of the Rx Desc list */
        handle->bd[i].Buffer = (NULL == rxBuff) ? 0 : (uint32_t)(rxBuff + (ETH_MAX_PACKET_SIZE * (i - txBuffCount)));
        handle->bd[i].C_S_L = (ETH_MAX_PACKET_SIZE << 16) |
                              EMAC_BD_FIELD_MSK(RX_IRQ) |
                              EMAC_BD_FIELD_MSK(RX_E);
    }

    /* For the last RX DMA Descriptor, it should be wrap back */
    handle->bd[handle->rxBuffLimit].C_S_L |= EMAC_BD_FIELD_MSK(RX_WR);

    /* For the TX DMA Descriptor, it will wrap to 0 according to EMAC_TX_BD_NUM*/
    BL_WR_REG(EMAC_BASE, EMAC_TX_BD_NUM, txBuffCount);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  Get TX MDA buffer descripter for data to send
 *
 * @param  handle: EMAC handle pointer
 * @param  txDMADesc: TX DMA descriptor pointer
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_DMATxDescGet(EMAC_Handle_Type *handle, EMAC_BD_Desc_Type **txDMADesc)
{
    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  Start TX
 *
 * @param  handle: EMAC handle pointer
 * @param  txDMADesc: TX DMA descriptor pointer
 * @param  len: len
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_StartTx(EMAC_Handle_Type *handle, EMAC_BD_Desc_Type *txDMADesc, uint32_t len)
{
    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  Enable EMAC module
 *
 * @param  None
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Enable(void)
{
    uint32_t tmpVal;

    /* Enable EMAC */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MODE);
    tmpVal = BL_SET_REG_BIT(tmpVal, EMAC_TXEN);
    tmpVal = BL_SET_REG_BIT(tmpVal, EMAC_RXEN);
    BL_WR_REG(EMAC_BASE, EMAC_MODE, tmpVal);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  EMAC_Enable_TX
 *
 * @param  None
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Enable_TX(void)
{
    uint32_t tmpVal;

    /* Enable EMAC */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MODE);
    tmpVal = BL_SET_REG_BIT(tmpVal, EMAC_TXEN);
    BL_WR_REG(EMAC_BASE, EMAC_MODE, tmpVal);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  EMAC_Disable_TX
 *
 * @param  None
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Disable_TX(void)
{
    uint32_t tmpVal;

    /* Enable EMAC */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MODE);
    tmpVal = BL_CLR_REG_BIT(tmpVal, EMAC_TXEN);
    BL_WR_REG(EMAC_BASE, EMAC_MODE, tmpVal);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  EMAC_Enable_RX
 *
 * @param  None
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Enable_RX(void)
{
    uint32_t tmpval;

    /* Enable EMAC TX*/
    tmpval = BL_RD_REG(EMAC_BASE, EMAC_MODE);
    tmpval = BL_SET_REG_BIT(tmpval, EMAC_RXEN);
    BL_WR_REG(EMAC_BASE, EMAC_MODE, tmpval);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  EMAC_Disable_RX
 *
 * @param  None
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Disable_RX(void)
{
    uint32_t tmpval;

    /* Disable EMAC RX*/
    tmpval = BL_RD_REG(EMAC_BASE, EMAC_MODE);
    tmpval = BL_CLR_REG_BIT(tmpval, EMAC_RXEN);
    BL_WR_REG(EMAC_BASE, EMAC_MODE, tmpval);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  Disable EMAC module
 *
 * @param  None
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_Disable(void)
{
    uint32_t tmpVal;

    /* Enable EMAC */
    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_MODE);
    tmpVal = BL_CLR_REG_BIT(tmpVal, EMAC_TXEN);
    tmpVal = BL_CLR_REG_BIT(tmpVal, EMAC_RXEN);
    BL_WR_REG(EMAC_BASE, EMAC_MODE, tmpVal);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  EMAC mask or unmask certain or all interrupt
 *
 * @param  intType: EMAC interrupt type
 * @param  intMask: EMAC interrupt mask value( MASK:disbale interrupt,UNMASK:enable interrupt )
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_IntMask(EMAC_INT_Type intType, BL_Mask_Type intMask)
{
    uint32_t tmpVal;

    /* Check the parameters */
    CHECK_PARAM(IS_BL_MASK_TYPE(intMask));

    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_INT_MASK);

    /* Mask or unmask certain or all interrupt */
    if (MASK == intMask) {
        tmpVal |= intType;
    } else {
        tmpVal &= (~intType);
    }

    /* Write back */
    BL_WR_REG(EMAC_BASE, EMAC_INT_MASK, tmpVal);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  Get EMAC interrupt status
 *
 * @param  intType: EMAC interrupt type
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Sts_Type EMAC_GetIntStatus(EMAC_INT_Type intType)
{
    uint32_t tmpVal;

    /* Check the parameters */
    CHECK_PARAM(IS_EMAC_INT_TYPE(intType));

    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_INT_SOURCE);

    return (tmpVal & intType) ? SET : RESET;
}

/****************************************************************************/ /**
 * @brief  Clear EMAC interrupt
 *
 * @param  intType: EMAC interrupt type
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_ClrIntStatus(EMAC_INT_Type intType)
{
    uint32_t tmpVal;

    /* Check the parameters */
    CHECK_PARAM(IS_EMAC_INT_TYPE(intType));

    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_INT_SOURCE);

    BL_WR_REG(EMAC_BASE, EMAC_INT_SOURCE, tmpVal | intType);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  EMAC_Int_Callback_Install
 *
 * @param  intIdx: EMAC_INT_Index
 * @param  cbFun: call back
 *
 * @return None
 *
*******************************************************************************/
BL_Err_Type EMAC_Int_Callback_Install(EMAC_INT_Index intIdx, intCallback_Type *cbFun)
{
    /* Check the parameters */

    emacIntCbfArra[intIdx] = cbFun;

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  EMAC_IRQHandler
 *
 * @param  None
 *
 * @return None
 *
*******************************************************************************/
void EMAC_IRQHandler(void)
{
    uint32_t tmpVal;

    tmpVal = BL_RD_REG(EMAC_BASE, EMAC_INT_MASK);

    if (SET == EMAC_GetIntStatus(EMAC_INT_TX_DONE) && !BL_IS_REG_BIT_SET(tmpVal, EMAC_TXB_M)) {
        EMAC_ClrIntStatus(EMAC_INT_TX_DONE);

        if (emacIntCbfArra[EMAC_INT_TX_DONE_IDX]) {
            emacIntCbfArra[EMAC_INT_TX_DONE_IDX]();
        }
    }

    if (SET == EMAC_GetIntStatus(EMAC_INT_TX_ERROR) && !BL_IS_REG_BIT_SET(tmpVal, EMAC_TXE_M)) {
        EMAC_ClrIntStatus(EMAC_INT_TX_ERROR);

        if (emacIntCbfArra[EMAC_INT_TX_ERROR_IDX]) {
            emacIntCbfArra[EMAC_INT_TX_ERROR_IDX]();
        }
    }

    if (SET == EMAC_GetIntStatus(EMAC_INT_RX_DONE) && !BL_IS_REG_BIT_SET(tmpVal, EMAC_RXB_M)) {
        EMAC_ClrIntStatus(EMAC_INT_RX_DONE);

        if (emacIntCbfArra[EMAC_INT_RX_DONE_IDX]) {
            emacIntCbfArra[EMAC_INT_RX_DONE_IDX]();
        }
    }

    if (SET == EMAC_GetIntStatus(EMAC_INT_RX_ERROR) && !BL_IS_REG_BIT_SET(tmpVal, EMAC_RXE_M)) {
        EMAC_ClrIntStatus(EMAC_INT_RX_ERROR);

        if (emacIntCbfArra[EMAC_INT_RX_ERROR_IDX]) {
            emacIntCbfArra[EMAC_INT_RX_ERROR_IDX]();
        }
    }

    if (SET == EMAC_GetIntStatus(EMAC_INT_RX_BUSY) && !BL_IS_REG_BIT_SET(tmpVal, EMAC_BUSY_M)) {
        EMAC_ClrIntStatus(EMAC_INT_RX_BUSY);

        if (emacIntCbfArra[EMAC_INT_RX_BUSY_IDX]) {
            emacIntCbfArra[EMAC_INT_RX_BUSY_IDX]();
        }
    }

    if (SET == EMAC_GetIntStatus(EMAC_INT_TX_CTRL) && !BL_IS_REG_BIT_SET(tmpVal, EMAC_TXC_M)) {
        EMAC_ClrIntStatus(EMAC_INT_TX_CTRL);

        if (emacIntCbfArra[EMAC_INT_TX_CTRL_IDX]) {
            emacIntCbfArra[EMAC_INT_TX_CTRL_IDX]();
        }
    }

    if (SET == EMAC_GetIntStatus(EMAC_INT_RX_CTRL) && !BL_IS_REG_BIT_SET(tmpVal, EMAC_RXC_M)) {
        EMAC_ClrIntStatus(EMAC_INT_RX_CTRL);

        if (emacIntCbfArra[EMAC_INT_RX_CTRL_IDX]) {
            emacIntCbfArra[EMAC_INT_RX_CTRL_IDX]();
        }
    }
}

/****************************************************************************/ /**
 * @brief  Request to pause TX
 *
 * @param  timeCount: Pause time count
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_TxPauseReq(uint16_t timeCount)
{
    BL_WR_REG(EMAC_BASE, EMAC_TXCTRL, (1 << 16) | timeCount);

    return SUCCESS;
}

/****************************************************************************/ /**
 * @brief  Set hash value
 *
 * @param  hash0: Hash value one
 * @param  hash1: Hash value two
 *
 * @return SUCCESS or ERROR
 *
*******************************************************************************/
BL_Err_Type EMAC_SetHash(uint32_t hash0, uint32_t hash1)
{
    BL_WR_REG(EMAC_BASE, EMAC_HASH0_ADDR, hash0);

    BL_WR_REG(EMAC_BASE, EMAC_HASH1_ADDR, hash1);

    return SUCCESS;
}

/*@} end of group EMAC_Public_Functions */

/*@} end of group EMAC */

/*@} end of group BL702_Peripheral_Driver */
