/***************************************************************************//** * \file cy_ethif.c * \version 1.0 * * Provides an API implementation of the ETHIF driver * ******************************************************************************** * \copyright * Copyright 2020 Cypress Semiconductor Corporation * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ #include "cy_device.h" #if defined (CY_IP_MXETH) #include "cy_ethif.h" #include <string.h> #include <stdlib.h> #if defined(__cplusplus) extern "C" { #endif /*************************************** * Local Variables ***************************************/ /** Cadence driver instantiation */ static CEDI_OBJ *cyp_ethif_gemgxlobj; /** Ethernet configurations */ static CEDI_Config cy_ethif_cfg; /** Cadence driver memory requirements */ static CEDI_SysReq cy_ethif_sysreq; /** Private data structures required for each instance of Ethernet IPs */ static CEDI_PrivateData * cyp_ethif_pd; /** Variables holding Statistics register values */ static CEDI_Statistics * cyp_ethif_statistic; /** Tx and Rx buffer */ uint8_t u8TxBuf[CY_ETH_TOTAL_TX_BUF][CY_ETH_SIZE_MAX_FRAME]; uint8_t u8RxBuf[CY_ETH_TOTAL_RX_BUF][CY_ETH_SIZE_MAX_FRAME]; /** Tx and Rx buffer status */ cy_stc_ethif_bufstatus_t cy_ethif_txBufStatus[CY_ETH_TOTAL_TX_BUF]; /** Buffer status will be CY_ETHIF_BUFFER_UNINIT */ cy_stc_ethif_bufstatus_t cy_ethif_rxBufStatus[CY_ETH_TOTAL_RX_BUF]; /** Buffer status will be CY_ETHIF_BUFFER_UNINIT */ /** Private data memory allocation */ uint8_t cy_ethif_privatedata[1800] = {0}; /** Tx descriptors */ uint8_t cy_ethif_tx_desc_list[CY_ETH_DEFINE_NUM_TXQS][CY_ETH_DEFINE_TOTAL_BD_PER_TXQUEUE + 1][CY_ETH_BD_SIZE]; /** Rx descriptors */ /** Cadence driver requires another set of buffers to replace the existing * buffers after a frame has been received. so, number of required BDs would not * be same as number of buffers */ uint8_t cy_ethif_rx_desc_list[CY_ETH_DEFINE_NUM_RXQS][((CY_ETH_DEFINE_TOTAL_BD_PER_TXQUEUE + 1) * 2)][CY_ETH_BD_SIZE]; /** Statistics registers */ uint8_t cy_ethif_statistic[160]; cy_stc_ethif_cb_t stccallbackfunctions; cy_stc_ethif_queue_disablestatus_t stcQueueDisStatus; bool bBufferInitialized = false; /***************************************************************************** * Local function prototypes ('static') *****************************************************************************/ static void Cy_ETHIF_EnableInterrupts(cy_stc_ethif_interruptconfig_t * pstcInterruptList); static void Cy_ETHIF_PrepareConfiguration(cy_stc_ethif_config_t * pstcEthIfConfig); static void Cy_ETHIF_AssignMemory(void); static void Cy_ETHIF_EventTx(void *pcy_privatedata, uint32_t u32event, uint8_t u8qnum); static void Cy_ETHIF_EventTxError(void *pcy_privatedata, uint32_t u32event, uint8_t u8qnum); static void Cy_ETHIF_EventRxFrame(void *pcy_privatedata, uint8_t u8qnum); static void Cy_ETHIF_EventRxError(void *pcy_privatedata, uint32_t a_event, uint8_t a_qnum); static void Cy_ETHIF_EventPhyManComplete(void *pcy_privatedata, uint8_t u8read, uint16_t u16ReadData); static void Cy_ETHIF_EventhrespError(void *pcy_privatedata, uint8_t u8qnum); static void Cy_ETHIF_EventLpPageRx(void* pcy_privatedata, struct CEDI_LpPageRx* pageRx); static void Cy_ETHIF_EventAn(void* pcy_privatedata, struct CEDI_NetAnStatus* netStat); static void Cy_ETHIF_EventLinkChange(void *pcy_privatedata, uint8_t a_linkstate); static void Cy_ETHIF_EventTsu(void *pcy_privatedata, uint32_t u32event); static void Cy_ETHIF_EventPauseFrame(void *pcy_privatedata, uint32_t u32event); static void Cy_ETHIF_EventPtp(void* pcy_privatedata, uint32_t u32type, struct CEDI_1588TimerVal* time); static void Cy_ETHIF_EventExternalInt(void * pcy_privatedata); static void Cy_ETHIF_EventWol(void * pcy_privatedata); static void Cy_ETHIF_EventLpi(void * pcy_privatedata); static void Cy_ETHIF_InitializeBuffers(void); static void Cy_ETHIF_ClearBuffer(uint32_t * pu32Buffer); static uint8_t Cy_ETHIF_GetBuf(bool bTransmitBuf); static cy_en_ethif_status_t Cy_ETHIF_WrapperConfig(cy_stc_ethif_wrapper_config_t * pstcWrapperConfig); static void Cy_ETHIF_IPEnable(void); static void Cy_ETHIF_IPDisable(void); static cy_en_ethif_status_t Cy_ETHIF_TSUInit(cy_stc_ethif_tsu_config_t * pstcTSUConfig); static cy_en_ethif_status_t Cy_ETHIF_DisableQueues(cy_stc_ethif_config_t * pstcEthIfConfig); /***************************************************************************** * Local Call back function supplied to Cadence driver *****************************************************************************/ CEDI_Callbacks Cy_ETHIF_Callbacks = { .phyManComplete = (CEDI_CbPhyManComplete)Cy_ETHIF_EventPhyManComplete, .txEvent = (CEDI_CbTxEvent)Cy_ETHIF_EventTx, .txError = (CEDI_CbTxError)Cy_ETHIF_EventTxError, .rxFrame = (CEDI_CbRxFrame)Cy_ETHIF_EventRxFrame, .rxError = (CEDI_CbRxError)Cy_ETHIF_EventRxError, .hrespError = (CEDI_CbHrespError)Cy_ETHIF_EventhrespError, .lpPageRx = (CEDI_CbLpPageRx)Cy_ETHIF_EventLpPageRx, .anComplete = (CEDI_CbAnComplete)Cy_ETHIF_EventAn, .linkChange = (CEDI_CbLinkChange)Cy_ETHIF_EventLinkChange, .tsuEvent = (CEDI_CbTsuEvent)Cy_ETHIF_EventTsu, .pauseEvent = (CEDI_CbPauseEvent)Cy_ETHIF_EventPauseFrame, .ptpPriFrameTx = (CEDI_CbPtpPriFrameTx)Cy_ETHIF_EventPtp, .ptpPeerFrameTx = (CEDI_CbPtpPeerFrameTx)Cy_ETHIF_EventPtp, .ptpPriFrameRx = (CEDI_CbPtpPriFrameRx)Cy_ETHIF_EventPtp, .ptpPeerFrameRx = (CEDI_CbPtpPeerFrameRx)Cy_ETHIF_EventPtp, .lpiStatus = (CEDI_CbLpiStatus)Cy_ETHIF_EventLpi, .wolEvent = (CEDI_CbWolEvent)Cy_ETHIF_EventWol, .extInpIntr = (CEDI_CbExtInpIntr)Cy_ETHIF_EventExternalInt }; /******************************************************************************* * Function Name: Cy_ETHIF_Init ****************************************************************************//** * * \brief Initializes the Ethernet MAC, Cadence Driver, EthIf and PHY * * \param pstcEthIfConfig * Pointer to Ethernet configuration parameters * * \param pstcInterruptList * List of Interrupts to enable * * \return CY_ETHIF_SUCCESS Ethernet MAC has been initialized along with * Cadence driver and external PHY * \return CY_ETHIF_BAD_PARAM If following conditions are met: * pstcEth == NULL * pstcEthIfConfig == NULL * pstcInterruptList == NULL * GEM_GXL Object could not be created * Memory assigned by Interface layer is not enough * Cadence driver could not initialize Ethernet MAC * CY_ETHIF_MEMORY_NOT_ENOUGH * Assigned memory for BDs or for Private data is * not enough * CY_ETHIF_LINK_DOWN Link is not yet up * * \ Note: * This function Initializes the Ethernet MAC, Cadence driver, EthIf layer and * external PHY with the provided parameters. Port init for the Ethernet must be * done before calling Cy_EthIf_Init function. Buffer configuration parameters * shall be done in EthIf.h file *******************************************************************************/ cy_en_ethif_status_t Cy_ETHIF_Init(cy_stc_ethif_config_t * pstcEthIfConfig, cy_stc_ethif_interruptconfig_t * pstcInterruptList) { // local variable declaration uint32_t u32RetValue = 0; uint8_t u8tmpcounter = 0; uint8_t u8tmpintrcntr = 0; bool bClearAll = true; bool bTransmitBuf = true; uint16_t u16SysReqTxBDLength = 0; uint16_t u16SysReqRxBDLength = 0; /* Parameter checks */ if ((pstcEthIfConfig == NULL) || (pstcInterruptList == NULL)) return CY_ETHIF_BAD_PARAM; else if (pstcEthIfConfig->pstcWrapperConfig == NULL) { return CY_ETHIF_BAD_PARAM; } if (bBufferInitialized == false) { /* Create GEM_GXL object */ cyp_ethif_gemgxlobj = CEDI_GetInstance(); if (cyp_ethif_gemgxlobj == NULL) { return CY_ETHIF_BAD_PARAM; } } /* Load Init parameter */ Cy_ETHIF_PrepareConfiguration(pstcEthIfConfig); if (pstcEthIfConfig->bintrEnable == true) { /* Configure Interrupts */ Cy_ETHIF_EnableInterrupts(pstcInterruptList); /* Init Callback functions */ stccallbackfunctions.rxframecb = NULL; stccallbackfunctions.txerrorcb = NULL; stccallbackfunctions.txcompletecb = NULL; stccallbackfunctions.tsuSecondInccb = NULL; } /* Initialize ENET MAC Wrapper */ if (CY_ETHIF_BAD_PARAM == Cy_ETHIF_WrapperConfig(pstcEthIfConfig->pstcWrapperConfig)) { Cy_ETHIF_IPDisable(); return CY_ETHIF_BAD_PARAM; } /* Enable the IP to access EMAC registers set */ Cy_ETHIF_IPEnable(); /* Probe for checking configuration parameters and calculating memory size */ (void)cyp_ethif_gemgxlobj->probe(&cy_ethif_cfg, &cy_ethif_sysreq); /* Check for assigned memory and required memory match */ u16SysReqTxBDLength = ((cy_ethif_sysreq.txDescListSize / CY_ETH_DEFINE_NUM_TXQS)/(CY_ETH_DEFINE_TOTAL_BD_PER_TXQUEUE + 1)); u16SysReqRxBDLength = ((cy_ethif_sysreq.rxDescListSize / CY_ETH_DEFINE_NUM_RXQS)/(CY_ETH_DEFINE_TOTAL_BD_PER_RXQUEUE + 1)); if ((u16SysReqTxBDLength != CY_ETH_BD_SIZE) || (u16SysReqRxBDLength != CY_ETH_BD_SIZE)) { /* Memory not enough */ return CY_ETHIF_MEMORY_NOT_ENOUGH; } if (sizeof(cy_ethif_privatedata)< cy_ethif_sysreq.privDataSize) { /* Memory not enough */ return CY_ETHIF_MEMORY_NOT_ENOUGH; } /* assign starting addresses to local variable */ Cy_ETHIF_AssignMemory(); /* Initialization EMAC registers */ u32RetValue = cyp_ethif_gemgxlobj->init((void *)cyp_ethif_pd, &cy_ethif_cfg, &Cy_ETHIF_Callbacks); if (u32RetValue == EINVAL || u32RetValue == ENOTSUP) { Cy_ETHIF_IPDisable(); return CY_ETHIF_BAD_PARAM; } /* Disable Transmit and Receive Queues */ Cy_ETHIF_DisableQueues(pstcEthIfConfig); /* TSU Initialization */ if (NULL != pstcEthIfConfig->pstcTSUConfig) { if (CY_ETHIF_BAD_PARAM == Cy_ETHIF_TSUInit(pstcEthIfConfig->pstcTSUConfig)) { Cy_ETHIF_IPDisable(); return CY_ETHIF_BAD_PARAM; } } /* Initialize Buffer status */ if (bBufferInitialized == false) { Cy_ETHIF_InitializeBuffers(); bBufferInitialized = true; } else { /* clear all released transmit buffer */ Cy_ETHIF_ClearReleasedBuf(bClearAll, bTransmitBuf); bTransmitBuf = false; /* clear all released receive buffer */ Cy_ETHIF_ClearReleasedBuf(bClearAll, bTransmitBuf); } /* allocate assign buffers to RX BDs */ for (u8tmpcounter = 0; u8tmpcounter < cy_ethif_cfg.rxQs; u8tmpcounter++) { for (u8tmpintrcntr = 0; u8tmpintrcntr < cy_ethif_cfg.rxQLen[u8tmpcounter]; u8tmpintrcntr++) { cyp_ethif_gemgxlobj->addRxBuf((void *)cyp_ethif_pd, u8tmpcounter, (CEDI_BuffAddr *)&cy_ethif_rxBufStatus[(u8tmpintrcntr + (u8tmpcounter*CY_ETH_DEFINE_TOTAL_BD_PER_RXQUEUE))].cy_ethif_bufaddr.vAddr, 0); cy_ethif_rxBufStatus[(u8tmpintrcntr + (u8tmpcounter*CY_ETH_DEFINE_TOTAL_BD_PER_RXQUEUE))].enBufStatus = CY_ETHIF_BUFFER_OCCUPIED; } } /* additional Receive configurations */ cyp_ethif_gemgxlobj->setCopyAllFrames((void *)cyp_ethif_pd, CY_ETH_ENABLE_1); cyp_ethif_gemgxlobj->setRxBadPreamble((void *)cyp_ethif_pd, CY_ETH_ENABLE_1); /* Do not drop frames with CRC error */ cyp_ethif_gemgxlobj->setIgnoreFcsRx((void *)cyp_ethif_pd, CY_ETH_ENABLE_1); // Optional: Setting Filter configuration // Optional: setting screen registers /* Enable MDIO */ cyp_ethif_gemgxlobj->setMdioEnable((void *)(void *)cyp_ethif_pd, CY_ETH_ENABLE_1); /* driver start */ cyp_ethif_gemgxlobj->start((void *)cyp_ethif_pd); return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_Init ****************************************************************************//** * * \brief Function loads callback functions to its local data structures * * \param cbFuncsList pointer to callback function list * *******************************************************************************/ void Cy_ETHIF_RegisterCallbacks(cy_stc_ethif_cb_t *cbFuncsList) { /* Load Callback functions */ stccallbackfunctions.rxframecb = cbFuncsList->rxframecb; stccallbackfunctions.txerrorcb = cbFuncsList->txerrorcb; stccallbackfunctions.txcompletecb = cbFuncsList->txcompletecb; stccallbackfunctions.tsuSecondInccb = cbFuncsList->tsuSecondInccb; } /******************************************************************************* * Function Name: Cy_ETHIF_TransmitFrame ****************************************************************************//** * * \brief Function initiates transmission based on passed arguments * * \param pu8TxBuffer pointer to Transmit source buffer * u16Length Length of data to transmit from source buffer, Length should include source * and destination buffer address. CRC bytes shall not be included in the length * u8QueueIndex Queue to be used to transmit the frame * bEndBuffer True - Last buffer of the frame to be transmitted * False - Other Buffers to be provided after function call * IP will not start transmitting until it gets EndBuffer True * * \param u16Length u16Length * * \param u8QueueIndex u8QueueIndex * * \param bEndBuffer bEndBuffer * * \return CY_ETHIF_SUCCESS Frame transmission started * CY_ETHIF_BAD_PARAM Parameter passed contains invalid values * CY_ETHIF_BUFFER_NOT_AVAILABLE Buffer not available to load the source data * * \note * *******************************************************************************/ cy_en_ethif_status_t Cy_ETHIF_TransmitFrame(uint8_t * pu8TxBuffer, uint16_t u16Length, uint8_t u8QueueIndex, bool bEndBuffer) { uint8_t u8BufferIndex = 0; uint8_t * pu8LocalBuf = 0; bool bTransmitBuffer = true; bool bClearAll = false; uint8_t u8flags = 0; // uint16_t u16idx = 0; uint32_t u32result = 0; /* Check for arguments */ if ((pu8TxBuffer == NULL) || (u16Length > CY_ETH_SIZE_MAX_FRAME) || (u8QueueIndex > CY_ETH_QS2_2)) { return CY_ETHIF_BAD_PARAM; } /* Check requested queue enabled or not */ if (stcQueueDisStatus.bTxQueueDisable[u8QueueIndex] == true) { /* Requested Queue is disabled */ return CY_ETHIF_BAD_PARAM; } /* Get available Tx Buffer from the Transmit buffer Pool */ u8BufferIndex = Cy_ETHIF_GetBuf(bTransmitBuffer); if (CY_ETHIF_NO_BUFFER_AVAILABLE == u8BufferIndex) { /* check for first released buffer */ u8BufferIndex = Cy_ETHIF_ClearReleasedBuf(bClearAll, bTransmitBuffer); if (CY_ETHIF_NO_BUFFER_AVAILABLE == u8BufferIndex) { return CY_ETHIF_BUFFER_NOT_AVAILABLE; // No buffer available } } /* Load the buffer address of available Buffer */ pu8LocalBuf = (uint8_t *)cy_ethif_txBufStatus[u8BufferIndex].cy_ethif_bufaddr.vAddr; /* change buffer's status to OCCUPIED, Buffer will be released in case of error or after Tx complete interrupt occurs */ cy_ethif_txBufStatus[u8BufferIndex].enBufStatus = CY_ETHIF_BUFFER_OCCUPIED; /* Copy data to un-cached aligned EthIf Tx buffer */ memcpy((&pu8LocalBuf[0]), &pu8TxBuffer[0], u16Length); /* Typecast bEndBuffer to Flag type */ // TODO: adapt function for CEDI_TXB_NO_AUTO_CRC and CEDI_TXB_NO_AUTO_START if (bEndBuffer == true) { u8flags = CEDI_TXB_LAST_BUFF; } /* Clear transmit status register before begin to transmit */ cyp_ethif_gemgxlobj->clearTxStatus((void *)cyp_ethif_pd, CY_ETHIF_TX_STATUS_CLEAR); /* Trigger Internal transmit function */ u32result = cyp_ethif_gemgxlobj->queueTxBuf((void *)cyp_ethif_pd, u8QueueIndex, &cy_ethif_txBufStatus[u8BufferIndex].cy_ethif_bufaddr, u16Length, u8flags); if (u32result != 0) { /* error */ cy_ethif_txBufStatus[u8BufferIndex].enBufStatus = CY_ETHIF_BUFFER_RELEASED; return CY_ETHIF_BAD_PARAM; } // TODO: wait until tx done successfully? return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_TxPauseFrame ****************************************************************************//** * * \brief Transmits IEEE 802.3X standard Pause Frame * * \param bZeroTQ True - Zero Time Quanta * bZeroTQ False - Transmit pause frame with set time quanta * * \return none * \note: If interrupt enabled, interrupt will be triggered at the end of the transmission * *******************************************************************************/ cy_en_ethif_status_t Cy_ETHIF_TxPauseFrame(bool bZeroTQ) { /* check for arguments */ if (bZeroTQ == true) { /* trigger Pause frame with Zero Time Quanta */ cyp_ethif_gemgxlobj->txZeroQPause((void *)cyp_ethif_pd); } else { cyp_ethif_gemgxlobj->txPauseFrame((void *)cyp_ethif_pd); } return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_ConfigPause ****************************************************************************//** * * \brief Configures the Pause Frame transmission according to IEEE 802.3X standard * * \param u16PauseQuanta Time Quanta * *******************************************************************************/ cy_en_ethif_status_t Cy_ETHIF_ConfigPause(uint16_t u16PauseQuanta) { /* Set Tx Pause Quanta for Priority 0 */ if (EOK != cyp_ethif_gemgxlobj->setTxPauseQuantum((void *)cyp_ethif_pd, u16PauseQuanta, CY_ETHIF_PAUSE_P0)) { return CY_ETHIF_BAD_PARAM; } /* Enable Receive Pause Frames */ cyp_ethif_gemgxlobj->setCopyPauseDisable((void *)cyp_ethif_pd, CY_ETH_DISABLE_0); /* Enable Pause Frames */ cyp_ethif_gemgxlobj->setPauseEnable((void *)cyp_ethif_pd, CY_ETH_ENABLE_1); return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_SetNoBroadCast ****************************************************************************//** * * \brief Disable/Enable receipt of broadcast frames * * \param rejectBC if =0 broadcasts are accepted, if =1 they are rejected. * *******************************************************************************/ void Cy_ETHIF_SetNoBroadCast(bool rejectBC) { cyp_ethif_gemgxlobj->setNoBroadcast((void *)cyp_ethif_pd,rejectBC); } /******************************************************************************* * Function Name: Cy_EthIf_SetCopyAllFrames ****************************************************************************//** * * \brief Enable/Disable copy all frames mode * * \param toBeEnabled if =1 enables copy all frames mode, if =0 then this is disabled * *******************************************************************************/ void Cy_ETHIF_SetCopyAllFrames(bool toBeEnabled) { cyp_ethif_gemgxlobj->setCopyAllFrames((void *)cyp_ethif_pd,toBeEnabled); } /******************************************************************************* * Function : Cy_ETHIF_SetFilterAddress ****************************************************************************//** * * \brief Set Filter Address with specific filter number * * \param filterNo Filter number * config Filter configuration for Ethernet MAC * * \param config config * * \return CY_ETHIF_SUCCESS Filter is set * CY_ETHIF_BAD_PARAM Parameter passed contains invalid values * * \note * Maximum 4 filters can be set * *******************************************************************************/ cy_en_ethif_status_t Cy_ETHIF_SetFilterAddress(cy_en_ethif_filter_num_t filterNo, const cy_stc_ethif_filter_config_t* config) { if(filterNo >= CY_ETH_FILTER_NUM_INV) { return CY_ETHIF_BAD_PARAM; } if(config == NULL) { return CY_ETHIF_BAD_PARAM; } /* add some address filters */ cyp_ethif_gemgxlobj->setSpecificAddr((void *)cyp_ethif_pd, filterNo, (CEDI_MacAddress*)&config->filterAddr, config->typeFilter, config->ignoreBytes); return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_PhyRegRead ****************************************************************************//** * * \brief Local function used by other APIs to read the PHY register * * \param u8RegNo Register to read * * \param u8PHYAddr u8PHYAddr * * \return read data from the register * * \note * CY_ETH_PHY_ADDR must match with PHY. * PHY data-sheet and hardware schematic shall be checked * *******************************************************************************/ uint32_t Cy_ETHIF_PhyRegRead(uint8_t u8RegNo, uint8_t u8PHYAddr) { uint32_t u32result; uint16_t u16ReadData; uint32_t nw_status; cyp_ethif_gemgxlobj->phyStartMdioRead( (void *)cyp_ethif_pd, CY_ETHIF_PHY_FLAG, u8PHYAddr, u8RegNo); while(1) { nw_status = cyp_ethif_gemgxlobj->getMdioIdle((void *)cyp_ethif_pd); if (nw_status != CY_ETH_MDIO_BUSY_0) break; } /* additional wait */ Cy_SysLib_DelayUs(800); // 800us delay u32result = cyp_ethif_gemgxlobj->getMdioReadData((void *)cyp_ethif_pd, &u16ReadData); if (u32result!=0) { // debug_printf("[ETH] PHY register read not success.\r\n"); } return (uint32_t)u16ReadData; } /******************************************************************************* * Function Name: Cy_ETHIF_PhyRegWrite ****************************************************************************//** * * \brief Local function used by other APIs to write the PHY register * * \param u8RegNo Register to write * \param u16Data data to write * \param u8PHYAddr u8PHYAddr * \return * * \note * u8PHYAddr must match with PHY. * PHY data-sheet and hardware schematic shall be checked * *******************************************************************************/ cy_en_ethif_status_t Cy_ETHIF_PhyRegWrite(uint8_t u8RegNo, uint16_t u16Data, uint8_t u8PHYAddr) { cyp_ethif_gemgxlobj->phyStartMdioWrite( (void *)cyp_ethif_pd, CY_ETHIF_PHY_FLAG, u8PHYAddr, u8RegNo, u16Data ); while (cyp_ethif_gemgxlobj->getMdioIdle((void *)cyp_ethif_pd) != CY_ETH_MDIO_BUSY_0); /* additional wait */ Cy_SysLib_DelayUs(200); // 200usec return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_ClearReleasedBuf ****************************************************************************//** * * \brief Each buffer goes through cycle of FREE - OCCUPIED - RELEASED - FREE * Function looks into status of each buffer and reset them to default values if status is RELEASED * * \param bClearAll True - Free all buffers which have status "CY_ETHIF_BUFFER_RELEASED" * False - Only first buffer found to be "CY_ETHIF_BUFFER_RELEASED" will be free * bTransmitBuf True - Free buffer from Transmit pool * False - Free buffer from Receive pool * * \param bTransmitBuf bTransmitBuf * * \return CY_ETHIF_BUFFER_AVAILABLE when Free all released buffers * CY_ETHIF_NO_BUFFER_AVAILABLE No Buffer in a state of "CY_ETHIF_BUFFER_RELEASED" * u8tmpcounter in case of bClearAll to false, function will break right after locating first released buffer * *******************************************************************************/ uint8_t Cy_ETHIF_ClearReleasedBuf (bool bClearAll, bool bTransmitBuf) { bool bBufferReleased = false; if (bTransmitBuf) { for (uint8_t u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_TX_BUF; u8tmpcounter++) { if (cy_ethif_txBufStatus[u8tmpcounter].enBufStatus == CY_ETHIF_BUFFER_RELEASED) { Cy_ETHIF_ClearBuffer((uint32_t *)cy_ethif_txBufStatus[u8tmpcounter].cy_ethif_bufaddr.vAddr); cy_ethif_txBufStatus[u8tmpcounter].enBufStatus = CY_ETHIF_BUFFER_FREE; bBufferReleased = true; if (bClearAll == false) { return u8tmpcounter; } } } } else { for (uint8_t u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_RX_BUF; u8tmpcounter++) { if (cy_ethif_rxBufStatus[u8tmpcounter].enBufStatus == CY_ETHIF_BUFFER_RELEASED) { Cy_ETHIF_ClearBuffer((uint32_t *)cy_ethif_rxBufStatus[u8tmpcounter].cy_ethif_bufaddr.vAddr); cy_ethif_rxBufStatus[u8tmpcounter].enBufStatus = CY_ETHIF_BUFFER_FREE; bBufferReleased = true; if (bClearAll == false) { return u8tmpcounter; } } } } if (bClearAll && bBufferReleased) return CY_ETHIF_BUFFER_AVAILABLE; else return CY_ETHIF_NO_BUFFER_AVAILABLE; } /******************************************************************************* * Function Name: Cy_ETHIF_GetTimerValue ****************************************************************************//** * * \brief Returns the current timer value from TSU register * * \param pstcRetTmrValue [out] pointer to data structure to return the values * *******************************************************************************/ cy_en_ethif_status_t Cy_ETHIF_Get1588TimerValue(CEDI_1588TimerVal* pstcRetTmrValue) { if (pstcRetTmrValue == NULL) { return CY_ETHIF_BAD_PARAM; } cyp_ethif_gemgxlobj->get1588Timer((void *)cyp_ethif_pd, pstcRetTmrValue); return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_SetTimerValue ****************************************************************************//** * * \brief Setting the current timer value in TSU register * * \param pstcTmrValue pointer to data structure to configure register with * *******************************************************************************/ cy_en_ethif_status_t Cy_ETHIF_Set1588TimerValue(CEDI_1588TimerVal * pstcTmrValue) { if (pstcTmrValue == NULL) { return CY_ETHIF_BAD_PARAM; } if (EOK != cyp_ethif_gemgxlobj->set1588Timer((void *)cyp_ethif_pd, pstcTmrValue)) { /* Reason could be Null pointer, hardware does not support TSU or pstcTimerValue.nanosecs>0x3FFFFFFF */ return CY_ETHIF_BAD_PARAM; } return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_DecodeEvent ****************************************************************************//** * * \brief Interrupt handler for Ethernet instance ETH0 * Function calls isr function to decode the event. * *******************************************************************************/ void Cy_ETHIF_DecodeEvent(void) { // volatile uint32_t u32result; cyp_ethif_gemgxlobj->isr((void *)cyp_ethif_pd); //if (u32result!=0) debug_printf("NG4 (0x%08x)\r\n", result); return; } /*############################################################################*/ /******************************************************************************* * Function Name: Cy_ETHIF_EnableInterrupts ****************************************************************************//** * * \brief Function initializes enabled Interrupt * * \param pstcInterruptList pointer to structure list * *******************************************************************************/ static void Cy_ETHIF_EnableInterrupts (cy_stc_ethif_interruptconfig_t * pstcInterruptList) { uint32_t u32InterruptEn = 0; if (pstcInterruptList->btsu_time_match == true) u32InterruptEn |= CEDI_EV_TSU_TIME_MATCH; if (pstcInterruptList->bwol_rx == true) u32InterruptEn |= CEDI_EV_WOL_RX; if (pstcInterruptList->blpi_ch_rx == true) u32InterruptEn |= CEDI_EV_LPI_CH_RX; if (pstcInterruptList->btsu_sec_inc == true) u32InterruptEn |= CEDI_EV_TSU_SEC_INC; if (pstcInterruptList->bptp_tx_pdly_rsp == true) u32InterruptEn |= CEDI_EV_PTP_TX_PDLY_RSP; if (pstcInterruptList->bptp_tx_pdly_req == true) u32InterruptEn |= CEDI_EV_PTP_TX_PDLY_REQ; if (pstcInterruptList->bptp_rx_pdly_rsp == true) u32InterruptEn |= CEDI_EV_PTP_RX_PDLY_RSP; if (pstcInterruptList->bptp_rx_pdly_req == true) u32InterruptEn |= CEDI_EV_PTP_RX_PDLY_REQ; if (pstcInterruptList->bptp_tx_sync == true) u32InterruptEn |= CEDI_EV_PTP_TX_SYNC; if (pstcInterruptList->bptp_tx_dly_req == true) u32InterruptEn |= CEDI_EV_PTP_TX_DLY_REQ; if (pstcInterruptList->bptp_rx_sync == true) u32InterruptEn |= CEDI_EV_PTP_RX_SYNC; if (pstcInterruptList->bptp_rx_dly_req == true) u32InterruptEn |= CEDI_EV_PTP_RX_DLY_REQ; if (pstcInterruptList->bpause_frame_tx == true) u32InterruptEn |= CEDI_EV_PAUSE_FRAME_TX; if (pstcInterruptList->bpause_time_zero == true) u32InterruptEn |= CEDI_EV_PAUSE_TIME_ZERO; if (pstcInterruptList->bpause_nz_qu_rx == true) u32InterruptEn |= CEDI_EV_PAUSE_NZ_QU_RX; if (pstcInterruptList->bhresp_not_ok == true) u32InterruptEn |= CEDI_EV_HRESP_NOT_OK; if (pstcInterruptList->brx_overrun == true) u32InterruptEn |= CEDI_EV_RX_OVERRUN; if (pstcInterruptList->btx_complete == true) u32InterruptEn |= CEDI_EV_TX_COMPLETE; if (pstcInterruptList->btx_fr_corrupt == true) u32InterruptEn |= CEDI_EV_TX_FR_CORRUPT; if (pstcInterruptList->btx_retry_ex_late_coll == true) u32InterruptEn |= CEDI_EV_TX_RETRY_EX_LATE_COLL; if (pstcInterruptList->btx_underrun == true) u32InterruptEn |= CEDI_EV_TX_UNDERRUN; if (pstcInterruptList->btx_used_read == true) u32InterruptEn |= CEDI_EV_TX_USED_READ; if (pstcInterruptList->brx_used_read == true) u32InterruptEn |= CEDI_EV_RX_USED_READ; if (pstcInterruptList->brx_complete == true) u32InterruptEn |= CEDI_EV_RX_COMPLETE; if (pstcInterruptList->bman_frame == true) u32InterruptEn |= CEDI_EV_MAN_FRAME; cy_ethif_cfg.intrEnable = u32InterruptEn; } /******************************************************************************* * Function Name: Cy_ETHIF_PrepareConfiguration ****************************************************************************//** * * \brief prepares configuration based on the parameter passed to Cy_ETHIF_Init * function. This prepared configuration which is dedicated for specific Ethernet * instance would be used to initialize Ethernet MAC * * \param config Pointer to Ethernet configuration passed from Application layer * * \Note: * *******************************************************************************/ static void Cy_ETHIF_PrepareConfiguration( cy_stc_ethif_config_t * config ) { uint8_t u8QueueCounter = 0; /* Clear configuration table */ memset((void *)&cy_ethif_cfg, 0, sizeof(cy_ethif_cfg)); /* Load GEM_GXL register base address */ cy_ethif_cfg.regBase = CY_ETH0_GEMGXL_ADDR_REGBASE; /* Prepare Queues */ cy_ethif_cfg.rxQs = CY_ETH_DEFINE_NUM_RXQS; cy_ethif_cfg.txQs = CY_ETH_DEFINE_NUM_TXQS; for (u8QueueCounter=0; u8QueueCounter<cy_ethif_cfg.rxQs; u8QueueCounter++) { cy_ethif_cfg.rxQLen[u8QueueCounter] = CY_ETH_DEFINE_TOTAL_BD_PER_RXQUEUE; } for (u8QueueCounter=0; u8QueueCounter<cy_ethif_cfg.txQs; u8QueueCounter++) { cy_ethif_cfg.txQLen[u8QueueCounter] = CY_ETH_DEFINE_TOTAL_BD_PER_TXQUEUE; } /* Prepare Network control Register */ cy_ethif_cfg.pfcMultiQuantum = 0; /* bit25 pfc_ctrl */ cy_ethif_cfg.enExtTsuPort = 0; /* bit23 ext_tsu_port_enable, Not supported by hardware */ cy_ethif_cfg.storeUdpTcpOffset = 0; /* bit22 store_udp_offset */ cy_ethif_cfg.altSgmiiEn = 0; /* bit21 alt_sgmii_mode, Not supported by hardware */ cy_ethif_cfg.enableMdio = 0; /* bit4 man_port_en, Bit is separately enabled during MDIO operation */ /* Prepare Network Configuration Register */ cy_ethif_cfg.uniDirEnable = 0; /* bit31 uni_direction_enable, Not supported by hardware */ cy_ethif_cfg.ignoreIpgRxEr = 0; /* bit30 ignore_ipg_rx_er, Not supported by hardware */ cy_ethif_cfg.enRxBadPreamble = config->u8enRxBadPreamble; /* bit29 nsp_change */ // cy_ethif_cfg[u8EthIfInstance].ifTypeSel = pstcEthIfConfig->ifTypeSel; /* bit27 sgmii_mode_enable (reserved) */ /* (see the following) */ // don't care /* bit26 ignore_rx_fcs */ cy_ethif_cfg.enRxHalfDupTx = 0; /* bit25 en_half_duplex_rx, not supported by hardware */ cy_ethif_cfg.chkSumOffEn = config->u8chkSumOffEn; /* bit24 receive_checksum_offload_enable */ cy_ethif_cfg.disCopyPause = config->u8disCopyPause; /* bit23 disable_copy_of_pause_frames */ if(ETH_AXI_MASTER_PRESENT == 1) { cy_ethif_cfg.dmaBusWidth = CEDI_DMA_BUS_WIDTH_64; /* bit22:21 data bus with */ } else { cy_ethif_cfg.dmaBusWidth = CEDI_DMA_BUS_WIDTH_32; /* bit22:21 data bus with */ } /* 00:32bit 01:64bit */ cy_ethif_cfg.mdcPclkDiv = config->mdcPclkDiv; /* bit20:18 mdc_clock_division */ /* 010: Divide 32 */ /* 011: Divide 48 */ // don't care /* bit17 fcs_remove */ cy_ethif_cfg.rxLenErrDisc = config->u8rxLenErrDisc; /* bit16 length_field_error_frame_discard */ cy_ethif_cfg.rxBufOffset = 0; /* bit15:14 receive_buffer_offset */ // don't care /* bit13 pause_enable */ // don't care /* bit12 retry_test */ //cy_ethif_cfg[u8EthIfInstance].ifTypeSel = pstcEthIfConfig->ifTypeSel /* bit11 pcs_select (reserved)*/ /* (see the following) */ //cy_ethif_cfg[u8EthIfInstance].ifTypeSel = pstcEthIfConfig->ifTypeSel /* bit10 gigabit_mode_enable */ /* (see the following) */ cy_ethif_cfg.extAddrMatch = 0; /* bit9 external_address_match_enable, not supported by hardware */ cy_ethif_cfg.rx1536ByteEn = config->u8rx1536ByteEn; /* bit8 receive_1536_byte_frames */ // don't care /* bit7 unicast_hash_enable */ // don't care /* bit6 multicast_hash_enable */ // don't care /* bit5 no_broadcast */ // don't care /* bit4 copy_all_frames */ cy_ethif_cfg.rxJumboFrEn = config->u8rxJumboFrEn; /* bit3 jumbo_frames */ // don't care /* bit2 discard_non_vlan_frames */ cy_ethif_cfg.fullDuplex = 1; /* bit1 full_duplex */ //cy_ethif_cfg[u8EthIfInstance].ifTypeSel = pstcEthIfConfig->ifTypeSel /* bit0 speed */ /* configuration for cy_ethif_cfg[u8EthIfInstance].ifTypeSel */ if ((config->pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_MII_10) || (config->pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RGMII_10) || (config->pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RMII_10)) { cy_ethif_cfg.ifTypeSel = CEDI_IFSP_10M_MII; } else if ((config->pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_MII_100) || (config->pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RMII_100) || (config->pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RGMII_100)) { cy_ethif_cfg.ifTypeSel = CEDI_IFSP_100M_MII; } else if ((config->pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_GMII_1000) || (config->pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RGMII_1000)) { cy_ethif_cfg.ifTypeSel = CEDI_IFSP_1000M_GMII; } /*=================================================================================================*/ /* CTL.ETH_MODE | Network_config[0] | Network_config[10] | PHY mode */ /* | (speed) | (gigabit_mode_enable) | */ /*=================================================================================================*/ /* 2'd0 | 0 | 0 | MII - 10Mbps */ /* 2'd0 | 1 | 0 | MII - 100Mbps */ /* 2'd1 | 0 | 1 | GMII - 1000Mbps */ /* 2'd2 | 0 | 0 | RGMII - 10Mbps (4bits/Cycle) */ /* 2'd2 | 1 | 0 | RGMII - 100Mbps (4bits/Cycle) */ /* 2'd2 | 0 | 1 | RGMII - 1000Mbps (8bits/Cycle) */ /* 2'd3 | 0 | 0 | RMII - 10Mbps */ /* 2'd3 | 1 | 0 | RMII - 100Mbps */ /*=================================================================================================*/ /* Prepare DMA Config register */ cy_ethif_cfg.dmaAddrBusWidth = 0; /* bit30 dma_addr_bus_width_1 */ /* 0:32bit 1:64bit */ cy_ethif_cfg.enTxExtBD = CY_ETH_DEFINE_BD; /* bit29 tx_bd_extended_mode_en */ cy_ethif_cfg.enRxExtBD = CY_ETH_DEFINE_BD; /* bit28 rx_bd_extended_mode_en */ cy_ethif_cfg.dmaCfgFlags = config->u8dmaCfgFlags; /* bit26 force_max_amba_burst_tx */ /* bit25 force_max_amba_burst_rx */ /* bit24 force_discard_on_err */ for (u8QueueCounter=0; u8QueueCounter<cy_ethif_cfg.rxQs; u8QueueCounter++) { cy_ethif_cfg.rxBufLength[u8QueueCounter] = CY_ETH_SIZE_BUF_TXQ_RXQ >> 6; /* bit23:16 rx_buf_size */ } cy_ethif_cfg.txPktBufSize = CY_ETH_TX_PBUF_SIZE; /* bit10 tx_pbuf_size */ cy_ethif_cfg.rxPktBufSize = CY_ETH_RX_PBUF_SIZE; /* bit9:8 rx_pbuf_size */ cy_ethif_cfg.dmaEndianism = 0; /* bit7 endian_swap_packet */ /* 0: little endian mode */ /* 1: endian swap mode enable for packet data (CEDI_END_SWAP_DATA) */ /* bit6 endian_swap_management */ /* 0: little endian mode */ /* 1: endian swap mode enable for management descriptor (CEDI_END_SWAP_DESC) */ cy_ethif_cfg.dmaDataBurstLen = config->dmaDataBurstLen; /* bit4:0 amba_burst_length */ /* 1xxxx: attempt use burst up to 16 (CEDI_DMA_DBUR_LEN_16) */ /* 01xxx: attempt use burst up to 8 (CEDI_DMA_DBUR_LEN_8) */ /* 001xx: attempt use burst up to 4 (CEDI_DMA_DBUR_LEN_4) */ /* 0001x: always use single burst */ /* 00001: always use single burst (CEDI_AMBD_BURST_LEN_1) */ /* 00000: best AXI burst up to 256 beats */ /* Prepare ddr and upper_rx_q_base_addr register (0x4c8, 0x4D4) */ cy_ethif_cfg.upper32BuffTxQAddr = 0; /* bit31:0 not used */ cy_ethif_cfg.upper32BuffRxQAddr = 0; /* bit31:0 not used */ /* axi_max_ */ cy_ethif_cfg.aw2wMaxPipeline = config->u8aw2wMaxPipeline; /* bit15:8 aw2w_max_pipeline */ cy_ethif_cfg.ar2rMaxPipeline = config->u8ar2rMaxPipeline; /* bit 7:0 ar2r_max_pipeline */ } /******************************************************************************* * Function Name: Cy_ETHIF_WrapperConfig ****************************************************************************//** * * \brief Function initializes Ethernet Wrapper to configure Interface mode, reference clock/divider etc * * \param u8EthIfInstance Ethernet Instance * \param pstcInterruptList pointer to structure list * *******************************************************************************/ static cy_en_ethif_status_t Cy_ETHIF_WrapperConfig( cy_stc_ethif_wrapper_config_t * pstcWrapperConfig ) { uint32_t mode=0; if (pstcWrapperConfig->stcInterfaceSel > CY_ETHIF_CTL_RMII_100) { return CY_ETHIF_BAD_PARAM; } if ((pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_MII_10) || (pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_MII_100)) { mode = 0; } else if (pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_GMII_1000) { mode = 1; } else if ((pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RGMII_10) || (pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RGMII_100) || (pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RGMII_1000)) { mode = 2; } else if ((pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RMII_10) || (pstcWrapperConfig->stcInterfaceSel == CY_ETHIF_CTL_RMII_100)) { mode = 3; } ETH_CTL = (ETH_CTL & (uint32_t)~(ETH_CTL_ETH_MODE_Msk | ETH_CTL_REFCLK_SRC_SEL_Msk | ETH_CTL_REFCLK_DIV_Msk)) | _VAL2FLD(ETH_CTL_ETH_MODE,mode) | _VAL2FLD(ETH_CTL_REFCLK_SRC_SEL, pstcWrapperConfig->bRefClockSource) | _VAL2FLD(ETH_CTL_REFCLK_DIV, (pstcWrapperConfig->u8RefClkDiv - 1)); return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_IPEnable ****************************************************************************//** * * \brief Function enables Ethernet MAC * * \param * *******************************************************************************/ static void Cy_ETHIF_IPEnable(void) { ETH_CTL |=_VAL2FLD(ETH_CTL_ENABLED, CY_ETH_ENABLE_1); } /******************************************************************************* * Function Name: Cy_ETHIF_IPDisable ****************************************************************************//** * * \brief Function Disables Ethernet MAC * * \param * *******************************************************************************/ static void Cy_ETHIF_IPDisable(void) { ETH_CTL &= (uint32_t)~(ETH_CTL_ENABLED_Msk); } /******************************************************************************* * Function Name: Cy_ETHIF_AssignMemory ****************************************************************************//** * * \brief Local function is used to initialize private data structure, tx and rx queue start address * * \param * *******************************************************************************/ static void Cy_ETHIF_AssignMemory(void) { cyp_ethif_pd = (CEDI_PrivateData *)cy_ethif_privatedata; cy_ethif_cfg.rxQAddr = (uintptr_t)cy_ethif_rx_desc_list; cy_ethif_cfg.txQAddr = (uintptr_t)cy_ethif_tx_desc_list; cyp_ethif_statistic = (CEDI_Statistics *)cy_ethif_statistic; cy_ethif_cfg.statsRegs = (uintptr_t)cyp_ethif_statistic; /** get the physical address */ cy_ethif_cfg.rxQPhyAddr = cy_ethif_cfg.rxQAddr; /** get the physical address */ cy_ethif_cfg.txQPhyAddr = cy_ethif_cfg.txQAddr; } /******************************************************************************* * Function Name: Cy_ETHIF_DisableQueues ****************************************************************************//** * \brief By default all activated queues in the IP are enabled. However, only required * queues for tx and rx shall be enabled to make internal process faster. * * \brief Function Disables Ethernet MAC * * \param u8EthIfInstance Ethernet Instance * *******************************************************************************/ static cy_en_ethif_status_t Cy_ETHIF_DisableQueues (cy_stc_ethif_config_t * pstcEthIfConfig) { uint8_t u8TxQueueCounter = 0; uint8_t u8RxQueueCounter = 0; /* Transmit Queue 0 */ if (pstcEthIfConfig->btxq0enable == false) { /* Disable the queue pointer */ ETH_TX_Q_PTR = (ETH_TX_Q_PTR&(uint32_t)~(ETH_TRANSMIT_Q_PTR_DMA_TX_DIS_Q_Msk)) | _VAL2FLD(ETH_TRANSMIT_Q_PTR_DMA_TX_DIS_Q, 1UL); stcQueueDisStatus.bTxQueueDisable[0] = true; } else u8TxQueueCounter++; /* Transmit Queue 1 */ if (pstcEthIfConfig->btxq1enable == false) { /* Disable the queue pointer */ ETH_TX_Q1_PTR = (ETH_TX_Q1_PTR&(uint32_t)~(ETH_TRANSMIT_Q1_PTR_DMA_TX_DIS_Q_Msk)) | _VAL2FLD(ETH_TRANSMIT_Q1_PTR_DMA_TX_DIS_Q, 1UL); stcQueueDisStatus.bTxQueueDisable[1] = true; } else u8TxQueueCounter++; /* Transmit Queue 2 */ if (pstcEthIfConfig->btxq2enable == false) { /* Disable the queue pointer */ ETH_TX_Q2_PTR = (ETH_TX_Q2_PTR&(uint32_t)~(ETH_TRANSMIT_Q2_PTR_DMA_TX_DIS_Q_Msk)) | _VAL2FLD(ETH_TRANSMIT_Q2_PTR_DMA_TX_DIS_Q, 1UL); stcQueueDisStatus.bTxQueueDisable[2] = true; } else u8TxQueueCounter++; /* Receive Queue 0 */ if (pstcEthIfConfig->brxq0enable == false) { /* Disable the queue pointer */ ETH_RX_Q_PTR = (ETH_RX_Q_PTR&(uint32_t)~(ETH_RECEIVE_Q_PTR_DMA_RX_DIS_Q_Msk)) | _VAL2FLD(ETH_RECEIVE_Q_PTR_DMA_RX_DIS_Q, 1UL); stcQueueDisStatus.bRxQueueDisable[0] = true; } else u8RxQueueCounter++; /* Receive Queue 1 */ if (pstcEthIfConfig->brxq1enable == false) { /* Disable the queue pointer */ ETH_RX_Q1_PTR = (ETH_RX_Q1_PTR&(uint32_t)~(ETH_RECEIVE_Q1_PTR_DMA_RX_DIS_Q_Msk)) | _VAL2FLD(ETH_RECEIVE_Q1_PTR_DMA_RX_DIS_Q, 1UL); stcQueueDisStatus.bRxQueueDisable[1] = true; } else u8RxQueueCounter++; /* Receive Queue 2 */ if (pstcEthIfConfig->brxq2enable == false) { /* Disable the queue pointer */ ETH_RX_Q2_PTR = (ETH_RX_Q2_PTR&(uint32_t)~(ETH_RECEIVE_Q2_PTR_DMA_RX_DIS_Q_Msk)) | _VAL2FLD(ETH_RECEIVE_Q2_PTR_DMA_RX_DIS_Q, 1UL); stcQueueDisStatus.bRxQueueDisable[2] = true; } else u8RxQueueCounter++; /* TODO: Temporarily in the driver. MUST be removed once IP is updated || Q3 for both Transmit and Receive has been removed from the IP Changes will apply to bitfile after 0513 release */ /* TODO: Idea of cross checking BD memory vs enabled queues */ return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_TSUInit ****************************************************************************//** * * \brief Function enables Time stamp unit in EMAC * * \param pstcTSUConfig Pointer to TSU parameters * * \return * *******************************************************************************/ static cy_en_ethif_status_t Cy_ETHIF_TSUInit (cy_stc_ethif_tsu_config_t * pstcTSUConfig) { /* set 1588 timer value */ /* Load Timer Value */ if (EOK != cyp_ethif_gemgxlobj->set1588Timer((void *)cyp_ethif_pd, pstcTSUConfig->pstcTimerValue)) { /* Reason could be Null pointer, hardware does not support TSU or pstcTimerValue.nanosecs>0x3FFFFFFF */ return CY_ETHIF_BAD_PARAM; } /* Timer increment register to achieve 1 second as precise as possible */ if (EOK != cyp_ethif_gemgxlobj->set1588TimerInc((void *)cyp_ethif_pd, pstcTSUConfig->pstcTimerIncValue)) { /* Reason could be Null pointer, hardware does not support TSU */ return CY_ETHIF_BAD_PARAM; } /* one step sync enabled */ if (EOK != cyp_ethif_gemgxlobj->set1588OneStepTxSyncEnable((void *)cyp_ethif_pd, (uint8_t) pstcTSUConfig->bOneStepTxSyncEnable)) { /* Reason could be Null pointer, hardware does not support TSU or bOneStepTxSyncEnable > 1 */ return CY_ETHIF_BAD_PARAM; } /* Set the descriptor time stamp Mode */ if (EOK != cyp_ethif_gemgxlobj->setDescTimeStampMode((void *)cyp_ethif_pd, pstcTSUConfig->enTxDescStoreTimeStamp, pstcTSUConfig->enRxDescStoreTimeStamp)) { /** Reason could be Null pointer, hardware does not support TSU, enTxDescStoreTimeStamp > CEDI_TX_TS_ALL, enRxDescStoreTimeStamp > CEDI_RX_TS_ALL */ return CY_ETHIF_BAD_PARAM; } /* disabled storing nanosecond in CRC field of received frame */ if (EOK != cyp_ethif_gemgxlobj->setStoreRxTimeStamp((void *)cyp_ethif_pd, (uint8_t) pstcTSUConfig->bStoreNSinRxDesc)) { /* Reason could be Null pointer, hardware does not support TSU or bStoreNSinRxDesc > 1 */ return CY_ETHIF_BAD_PARAM; } return CY_ETHIF_SUCCESS; } /******************************************************************************* * Function Name: Cy_ETHIF_InitializeBuffers ****************************************************************************//** * * \brief Function initializes the buffer status and clears the memory with * CY_EHTIF_EMPTYVALUE value. * * \param none * *******************************************************************************/ static void Cy_ETHIF_InitializeBuffers (void) { uint8_t u8tmpcounter; // Clear all TX buffers for (u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_TX_BUF; u8tmpcounter++) { cy_ethif_txBufStatus[u8tmpcounter].cy_ethif_bufaddr.vAddr = (uintptr_t) &u8TxBuf[u8tmpcounter][0]; cy_ethif_txBufStatus[u8tmpcounter].cy_ethif_bufaddr.pAddr = (uintptr_t) &u8TxBuf[u8tmpcounter][0]; cy_ethif_txBufStatus[u8tmpcounter].enBufStatus = CY_ETHIF_BUFFER_FREE; // Load Buffer with dummy values Cy_ETHIF_ClearBuffer((uint32_t*)&u8TxBuf[u8tmpcounter][0]); } // Clear all RX buffers for (u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_RX_BUF; u8tmpcounter++) { cy_ethif_rxBufStatus[u8tmpcounter].cy_ethif_bufaddr.vAddr = (uintptr_t) &u8RxBuf[u8tmpcounter][0]; cy_ethif_rxBufStatus[u8tmpcounter].cy_ethif_bufaddr.pAddr = (uintptr_t) &u8RxBuf[u8tmpcounter][0]; cy_ethif_rxBufStatus[u8tmpcounter].enBufStatus = CY_ETHIF_BUFFER_FREE; // Load Buffer with dummy values Cy_ETHIF_ClearBuffer((uint32_t*)&u8RxBuf[u8tmpcounter][0]); } } /******************************************************************************* * Function Name: Cy_ETHIF_ClearBuffer ****************************************************************************//** * * \brief Initializes buffer with the CY_EHTIF_EMPTYVALUE value * * \param pu32Buffer start address for the buffer * *******************************************************************************/ static void Cy_ETHIF_ClearBuffer (uint32_t * pu32Buffer) { for (uint16_t u16tmpcounter = 0; u16tmpcounter < (CY_ETH_SIZE_MAX_FRAME/4); u16tmpcounter++) { /* Load Buffer with dummy values */ pu32Buffer[u16tmpcounter] = CY_EHTIF_EMPTYVALUE; } } /******************************************************************************* * Function Name: Cy_ETHIF_GetBuf ****************************************************************************//** * * \brief returns the free buffer number which driver can start working with. * * \param bTransmitBuf To identify which pool caller wants to find free Buffer from * * \return u8invalid CY_ETHIF_NO_BUFFER_AVAILABLE when no buffer is free * u8tmpcounter counter value loaded with the free buffer instance * *******************************************************************************/ static uint8_t Cy_ETHIF_GetBuf (bool bTransmitBuf) { uint8_t u8invalid = CY_ETHIF_NO_BUFFER_AVAILABLE; static uint8_t u8TxBufferPtr = 0; static uint8_t u8RxBufferPtr = 0; if (bTransmitBuf) { for (uint8_t u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_TX_BUF; u8tmpcounter++) { if (cy_ethif_txBufStatus[(u8TxBufferPtr + u8tmpcounter)].enBufStatus == CY_ETHIF_BUFFER_FREE) { u8tmpcounter = u8TxBufferPtr; u8TxBufferPtr++; if (u8TxBufferPtr >= CY_ETH_TOTAL_TX_BUF) u8TxBufferPtr = 0; return u8tmpcounter; } u8TxBufferPtr++; if (u8TxBufferPtr >= CY_ETH_TOTAL_TX_BUF) u8TxBufferPtr = 0; } } else { for (uint8_t u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_RX_BUF; u8tmpcounter++) { if (cy_ethif_rxBufStatus[(u8RxBufferPtr + u8tmpcounter)].enBufStatus == CY_ETHIF_BUFFER_FREE) { u8tmpcounter = u8RxBufferPtr; u8RxBufferPtr++; if (u8RxBufferPtr >= CY_ETH_TOTAL_RX_BUF) u8RxBufferPtr = 0; return u8tmpcounter; } u8RxBufferPtr++; if (u8RxBufferPtr >= CY_ETH_TOTAL_RX_BUF) u8RxBufferPtr = 0; } } return u8invalid; } /******************************************************************************* * Function Name: Cy_ETHIF_EventTx ****************************************************************************//** * * \brief Function called by cadence driver upon getting Tx Event * * \param pcy_privatedata Instance specific private data * \param u32event occurred event * \param u8qnum Queue number * *******************************************************************************/ static void Cy_ETHIF_EventTx(void *pcy_privatedata, uint32_t u32event, uint8_t u8qnum) { CEDI_TxDescData Tx_DescData; if ((u32event&CEDI_EV_TX_COMPLETE) != 0) { cyp_ethif_gemgxlobj->freeTxDesc((void *)cyp_ethif_pd, u8qnum, &Tx_DescData); /* application callback function */ if (stccallbackfunctions.txcompletecb != NULL) { stccallbackfunctions.txcompletecb(u8qnum); } /* Release the buffer */ for (uint8_t u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_TX_BUF; u8tmpcounter++) { if ((uint32_t*)Tx_DescData.bufAdd.pAddr == (uint32_t*)cy_ethif_txBufStatus[u8tmpcounter].cy_ethif_bufaddr.pAddr) { /* Release the buffer */ cy_ethif_txBufStatus[u8tmpcounter].enBufStatus = CY_ETHIF_BUFFER_RELEASED; break; } } } return; } /******************************************************************************* * Function Name: Cy_ETHIF_EventTxError ****************************************************************************//** * * \brief Function called by cadence driver upon getting Tx Error Event * * \param pcy_privatedata Instance specific private data * \param u32event occurred event * \param u8qnum Queue number * *******************************************************************************/ static void Cy_ETHIF_EventTxError(void *pcy_privatedata, uint32_t u32event, uint8_t u8qnum) { CEDI_TxDescData Tx_DescData; cyp_ethif_gemgxlobj->freeTxDesc((void *)cyp_ethif_pd, u8qnum, &Tx_DescData); /** application callback function */ if (stccallbackfunctions.txerrorcb != NULL) { stccallbackfunctions.txerrorcb(u8qnum); } /* Release the buffer */ for (uint8_t u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_TX_BUF; u8tmpcounter++) { if ((uint32_t*)Tx_DescData.bufAdd.pAddr == (uint32_t*)cy_ethif_txBufStatus[u8tmpcounter].cy_ethif_bufaddr.pAddr) { cy_ethif_txBufStatus[u8tmpcounter].enBufStatus = CY_ETHIF_BUFFER_RELEASED; break; } } return; } /******************************************************************************* * Function Name: Cy_ETHIF_EventRxFrame ****************************************************************************//** * * \brief Function called by cadence driver upon getting Rx Event * * \param pcy_privatedata Instance specific private data * \param u8qnum Queue number * *******************************************************************************/ static void Cy_ETHIF_EventRxFrame(void *pcy_privatedata, uint8_t u8qnum) { uint32_t u32Result; uint32_t u32RxNum; // uint32_t u32RxStatus = 0; CEDI_BuffAddr TmpBufAddr; CEDI_RxDescData Rx_DescData; CEDI_RxDescStat Rx_DescStat; bool bReceiveBuffer = false; /* Value must be false for Receive buffers */ uint8_t u8BufferIndex = 255; bool bClearAll = false; /* number of used buffers */ u32RxNum = cyp_ethif_gemgxlobj->numRxUsed((void *)cyp_ethif_pd, u8qnum); /** read receive queue */ while (u32RxNum!=0) { /* Get the new Buffer to replace the used one */ u8BufferIndex = Cy_ETHIF_GetBuf(bReceiveBuffer); if (CY_ETHIF_NO_BUFFER_AVAILABLE == u8BufferIndex) { /* check for first released buffer */ u8BufferIndex = Cy_ETHIF_ClearReleasedBuf(bClearAll, bReceiveBuffer); if (CY_ETHIF_NO_BUFFER_AVAILABLE == u8BufferIndex) { return; // No buffer available } } TmpBufAddr.vAddr = cy_ethif_rxBufStatus[u8BufferIndex].cy_ethif_bufaddr.vAddr; TmpBufAddr.pAddr = cy_ethif_rxBufStatus[u8BufferIndex].cy_ethif_bufaddr.pAddr; u32Result = cyp_ethif_gemgxlobj->readRxBuf((void *)cyp_ethif_pd, u8qnum, &TmpBufAddr, CY_ETHIF_BUFFER_CLEARED_0, &Rx_DescData); if (u32Result != 0) { // debug_printf("[ETH] NG4 (0x%08x)\r\n", u32Result); } else { /* change buffer status to OCCUPIED */ cy_ethif_rxBufStatus[u8BufferIndex].enBufStatus = CY_ETHIF_BUFFER_OCCUPIED; } switch (Rx_DescData.status) { case CEDI_RXDATA_SOF_EOF: // 0 /* receive start and end frame */ cyp_ethif_gemgxlobj->getRxDescStat((void *)cyp_ethif_pd, Rx_DescData.rxDescStat, &Rx_DescStat); /* application callback function */ if (stccallbackfunctions.rxframecb != NULL) { stccallbackfunctions.rxframecb((uint8_t*)TmpBufAddr.pAddr, Rx_DescStat.bufLen); } /* Release the buffer */ for (uint8_t u8tmpcounter = 0; u8tmpcounter < CY_ETH_TOTAL_RX_BUF; u8tmpcounter++) { if ((uint32_t*)TmpBufAddr.pAddr == (uint32_t*)cy_ethif_rxBufStatus[u8tmpcounter].cy_ethif_bufaddr.pAddr) { cy_ethif_rxBufStatus[u8tmpcounter].enBufStatus = CY_ETHIF_BUFFER_RELEASED; break; } } break; case CEDI_RXDATA_SOF_ONLY: // 1 /* fragment start */ // debug_printf("[ETH] (SOF)Don't use fragment yet...\r\n"); break; //return; case CEDI_RXDATA_NO_FLAG: // 2 /* fragment */ // debug_printf("[ETH] (NOF)Don't use fragment yet...\r\n"); break; //return; case CEDI_RXDATA_EOF_ONLY: // 3 /* fragment end */ // debug_printf("[ETH] (EOF)Don't use fragment yet...\r\n"); break; case CEDI_RXDATA_NODATA: // 4 /* normal leaving */ // debug_printf("[ETH] NG5 RXDATA_NODATA\r\n"); return; /* from here it breaks while loop */ default: /* Unknown status */ break; } u32RxNum--; } } /******************************************************************************* * Function Name: Cy_ETHIF_EventRxError ****************************************************************************//** * * \brief Function called by cadence driver upon getting Rx Error Event * * \param pcy_privatedata Instance specific private data * \param u32event occurred event * \param u8qnum Queue number * *******************************************************************************/ static void Cy_ETHIF_EventRxError(void *pcy_privatedata, uint32_t a_event, uint8_t a_qnum) { //printf("[ETH] (Event) RxError received.\r\n"); return; } /******************************************************************************* * Function Name: Cy_ETHIF_EventPhyManComplete ****************************************************************************//** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventPhyManComplete(void *pcy_privatedata, uint8_t u8read, uint16_t u16ReadData) { // uint32_t u32temp; // uint32_t u32addr; // u32temp = *((volatile uint32_t*)0xXXXX); // u32addr = (u32temp & 0x007C0000) >> 18; // debug_printf("[ETH] (Event) PhyManComplete.\r\n"); // debug_printf("[ETH] w/r=%d, addr=0x%02x, data=0x%04x\r\n", (uint32_t)u8read, addr, (uint32_t)u16ReadData); return; } /******************************************************************************* * Function Name: Cy_ETHIF_EventhrespError ****************************************************************************//** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventhrespError(void *pcy_privatedata, uint8_t u8qnum) { // debug_printf("[ETH] (Event) hrespError received.\r\n"); // debug_printf("[ETH] queue num=%d\r\n", u8qnum); return; } /******************************************************************************* * Function Name: Cy_ETHIF_EventLpPageRx ****************************************************************************//** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventLpPageRx(void* pcy_privatedata, struct CEDI_LpPageRx* pageRx) { // debug_printf("Reports PCS auto-negotiation page received"); } /******************************************************************************* * Function Name: Cy_ETHIF_EventAn ****************************************************************************//** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventAn(void* pcy_privatedata, struct CEDI_NetAnStatus* netStat) { // debug_printf("Auto Negotiation Event"); } /******************************************************************************* * Function Name: Cy_ETHIF_EventLinkChange ****************************************************************************//** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventLinkChange(void *pcy_privatedata, uint8_t a_linkstate) { // debug_printf("[ETH] (Event) linkChange received.\r\n"); // debug_printf("[ETH] link state=%d\r\n", a_linkstate); return; } /******************************************************************************* * Function Name: Cy_ETHIF_EventTsu ****************************************************************************//** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventTsu (void *pcy_privatedata, uint32_t u32event) { /** Event generated if second count of the timer has incremented */ if (u32event & CEDI_EV_TSU_SEC_INC) { /** application callback function */ if (stccallbackfunctions.tsuSecondInccb != NULL) { stccallbackfunctions.tsuSecondInccb(); } } /** Timer count matched event */ if (u32event & CEDI_EV_TSU_TIME_MATCH) { } } /******************************************************************************* * Function Name: Cy_ETHIF_EventPauseFrame ****************************************************************************//** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventPauseFrame(void *pcy_privatedata, uint32_t u32event) { if (u32event & CEDI_EV_PAUSE_FRAME_TX) { // debug_printf("Pause frame transmitted"); } if (u32event & CEDI_EV_PAUSE_NZ_QU_RX) { // debug_printf("Pause frame received"); } } /******************************************************************************* * Function Name: Cy_ETHIF_EventPtp ******************************************************************************** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventPtp (void* pcy_privatedata, uint32_t u32type, struct CEDI_1588TimerVal* time) { if (u32type & CEDI_EV_PTP_TX_SYNC) { // printf("Sync frame transmitted"); } if (u32type & CEDI_EV_PTP_TX_PDLY_REQ) { // printf("PTP PDelay Req frame transmitted"); } if (u32type & CEDI_EV_PTP_TX_PDLY_RSP) { // printf("PTP PDelay Resp frame transmitted"); } if (u32type & CEDI_EV_PTP_RX_SYNC) { // printf("Sync frame received"); } if (u32type & CEDI_EV_PTP_RX_PDLY_REQ) { // printf("PTP PDelay Req frame received"); } if (u32type & CEDI_EV_PTP_RX_PDLY_RSP) { // printf("PTP PDelay Resp frame received"); } } /******************************************************************************* * Function Name: Cy_ETHIF_EventExternalInt ******************************************************************************** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventExternalInt(void * pcy_privatedata) { // debug_printf("External Event Occurred"); } /******************************************************************************* * Function Name: Cy_ETHIF_EventWol ******************************************************************************** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventWol(void * pcy_privatedata) { // debug_printf("Wake On LAN Event Occurred"); } /******************************************************************************* * Function Name: Cy_ETHIF_EventLpi ******************************************************************************** * * \brief * * \param * * *******************************************************************************/ static void Cy_ETHIF_EventLpi(void * pcy_privatedata) { // debug_printf("LPI Status changed Event"); } #if defined(__cplusplus) } #endif #endif /* CY_IP_MXETH */ /* [] END OF FILE */