Path: blob/main/sys/contrib/ncsw/Peripherals/FM/MAC/dtsec.c
48524 views
/*1* Copyright 2008-2013 Freescale Semiconductor Inc.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions are met:5* * Redistributions of source code must retain the above copyright6* notice, this list of conditions and the following disclaimer.7* * Redistributions in binary form must reproduce the above copyright8* notice, this list of conditions and the following disclaimer in the9* documentation and/or other materials provided with the distribution.10* * Neither the name of Freescale Semiconductor nor the11* names of its contributors may be used to endorse or promote products12* derived from this software without specific prior written permission.13*14*15* ALTERNATIVELY, this software may be distributed under the terms of the16* GNU General Public License ("GPL") as published by the Free Software17* Foundation, either version 2 of that License or (at your option) any18* later version.19*20* THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY21* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED22* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE23* DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY24* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES25* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;26* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND27* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT28* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS29* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.30*/3132/******************************************************************************33@File dtsec.c3435@Description FMan dTSEC driver36*//***************************************************************************/3738#include "std_ext.h"39#include "error_ext.h"40#include "string_ext.h"41#include "xx_ext.h"42#include "endian_ext.h"43#include "debug_ext.h"44#include "crc_mac_addr_ext.h"4546#include "fm_common.h"47#include "dtsec.h"48#include "fsl_fman_dtsec.h"49#include "fsl_fman_dtsec_mii_acc.h"5051/*****************************************************************************/52/* Internal routines */53/*****************************************************************************/5455static t_Error CheckInitParameters(t_Dtsec *p_Dtsec)56{57if (ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_10000)58RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 1G MAC driver only supports 1G or lower speeds"));59if (p_Dtsec->macId >= FM_MAX_NUM_OF_1G_MACS)60RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId can not be greater than the number of 1G MACs"));61if (p_Dtsec->addr == 0)62RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC Must have a valid MAC Address"));63if ((ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_1000) &&64p_Dtsec->p_DtsecDriverParam->halfdup_on)65RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC 1G can't work in half duplex"));66if (p_Dtsec->p_DtsecDriverParam->halfdup_on && (p_Dtsec->p_DtsecDriverParam)->loopback)67RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("LoopBack is not supported in halfDuplex mode"));68#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A00169if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev <= 6) /* fixed for rev3 */70if (p_Dtsec->p_DtsecDriverParam->rx_preamble)71RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("preambleRxEn"));72#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */73if (((p_Dtsec->p_DtsecDriverParam)->tx_preamble || (p_Dtsec->p_DtsecDriverParam)->rx_preamble) &&( (p_Dtsec->p_DtsecDriverParam)->preamble_len != 0x7))74RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Preamble length should be 0x7 bytes"));75if ((p_Dtsec->p_DtsecDriverParam)->halfdup_on &&76(p_Dtsec->p_DtsecDriverParam->tx_time_stamp_en || p_Dtsec->p_DtsecDriverParam->rx_time_stamp_en))77RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dTSEC in half duplex mode has to be with 1588 timeStamping diable"));78if ((p_Dtsec->p_DtsecDriverParam)->rx_flow && (p_Dtsec->p_DtsecDriverParam)->rx_ctrl_acc )79RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Receive control frame are not passed to the system memory so it can not be accept "));80if ((p_Dtsec->p_DtsecDriverParam)->rx_prepend > MAX_PACKET_ALIGNMENT)81RETURN_ERROR(MAJOR, E_INVALID_STATE, ("packetAlignmentPadding can't be greater than %d ",MAX_PACKET_ALIGNMENT ));82if (((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg1 > MAX_INTER_PACKET_GAP) ||83((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg2 > MAX_INTER_PACKET_GAP) ||84((p_Dtsec->p_DtsecDriverParam)->back_to_back_ipg > MAX_INTER_PACKET_GAP))85RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inter packet gap can't be greater than %d ",MAX_INTER_PACKET_GAP ));86if ((p_Dtsec->p_DtsecDriverParam)->halfdup_alt_backoff_val > MAX_INTER_PALTERNATE_BEB)87RETURN_ERROR(MAJOR, E_INVALID_STATE, ("alternateBackoffVal can't be greater than %d ",MAX_INTER_PALTERNATE_BEB ));88if ((p_Dtsec->p_DtsecDriverParam)->halfdup_retransmit > MAX_RETRANSMISSION)89RETURN_ERROR(MAJOR, E_INVALID_STATE, ("maxRetransmission can't be greater than %d ",MAX_RETRANSMISSION ));90if ((p_Dtsec->p_DtsecDriverParam)->halfdup_coll_window > MAX_COLLISION_WINDOW)91RETURN_ERROR(MAJOR, E_INVALID_STATE, ("collisionWindow can't be greater than %d ",MAX_COLLISION_WINDOW ));9293/* If Auto negotiation process is disabled, need to */94/* Set up the PHY using the MII Management Interface */95if (p_Dtsec->p_DtsecDriverParam->tbipa > MAX_PHYS)96RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("PHY address (should be 0-%d)", MAX_PHYS));97if (!p_Dtsec->f_Exception)98RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Exception"));99if (!p_Dtsec->f_Event)100RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Event"));101102#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002103if (p_Dtsec->p_DtsecDriverParam->rx_len_check)104RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));105#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */106107return E_OK;108}109110/* ......................................................................... */111112static uint32_t GetMacAddrHashCode(uint64_t ethAddr)113{114uint32_t crc;115116/* CRC calculation */117GET_MAC_ADDR_CRC(ethAddr, crc);118119crc = GetMirror32(crc);120121return crc;122}123124/* ......................................................................... */125126static void UpdateStatistics(t_Dtsec *p_Dtsec)127{128uint32_t car1, car2;129130fman_dtsec_get_clear_carry_regs(p_Dtsec->p_MemMap, &car1, &car2);131132if (car1)133{134if (car1 & CAR1_TR64)135p_Dtsec->internalStatistics.tr64 += VAL22BIT;136if (car1 & CAR1_TR127)137p_Dtsec->internalStatistics.tr127 += VAL22BIT;138if (car1 & CAR1_TR255)139p_Dtsec->internalStatistics.tr255 += VAL22BIT;140if (car1 & CAR1_TR511)141p_Dtsec->internalStatistics.tr511 += VAL22BIT;142if (car1 & CAR1_TRK1)143p_Dtsec->internalStatistics.tr1k += VAL22BIT;144if (car1 & CAR1_TRMAX)145p_Dtsec->internalStatistics.trmax += VAL22BIT;146if (car1 & CAR1_TRMGV)147p_Dtsec->internalStatistics.trmgv += VAL22BIT;148if (car1 & CAR1_RBYT)149p_Dtsec->internalStatistics.rbyt += (uint64_t)VAL32BIT;150if (car1 & CAR1_RPKT)151p_Dtsec->internalStatistics.rpkt += VAL22BIT;152if (car1 & CAR1_RMCA)153p_Dtsec->internalStatistics.rmca += VAL22BIT;154if (car1 & CAR1_RBCA)155p_Dtsec->internalStatistics.rbca += VAL22BIT;156if (car1 & CAR1_RXPF)157p_Dtsec->internalStatistics.rxpf += VAL16BIT;158if (car1 & CAR1_RALN)159p_Dtsec->internalStatistics.raln += VAL16BIT;160if (car1 & CAR1_RFLR)161p_Dtsec->internalStatistics.rflr += VAL16BIT;162if (car1 & CAR1_RCDE)163p_Dtsec->internalStatistics.rcde += VAL16BIT;164if (car1 & CAR1_RCSE)165p_Dtsec->internalStatistics.rcse += VAL16BIT;166if (car1 & CAR1_RUND)167p_Dtsec->internalStatistics.rund += VAL16BIT;168if (car1 & CAR1_ROVR)169p_Dtsec->internalStatistics.rovr += VAL16BIT;170if (car1 & CAR1_RFRG)171p_Dtsec->internalStatistics.rfrg += VAL16BIT;172if (car1 & CAR1_RJBR)173p_Dtsec->internalStatistics.rjbr += VAL16BIT;174if (car1 & CAR1_RDRP)175p_Dtsec->internalStatistics.rdrp += VAL16BIT;176}177if (car2)178{179if (car2 & CAR2_TFCS)180p_Dtsec->internalStatistics.tfcs += VAL12BIT;181if (car2 & CAR2_TBYT)182p_Dtsec->internalStatistics.tbyt += (uint64_t)VAL32BIT;183if (car2 & CAR2_TPKT)184p_Dtsec->internalStatistics.tpkt += VAL22BIT;185if (car2 & CAR2_TMCA)186p_Dtsec->internalStatistics.tmca += VAL22BIT;187if (car2 & CAR2_TBCA)188p_Dtsec->internalStatistics.tbca += VAL22BIT;189if (car2 & CAR2_TXPF)190p_Dtsec->internalStatistics.txpf += VAL16BIT;191if (car2 & CAR2_TDRP)192p_Dtsec->internalStatistics.tdrp += VAL16BIT;193}194}195196/* .............................................................................. */197198static uint16_t DtsecGetMaxFrameLength(t_Handle h_Dtsec)199{200t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;201202SANITY_CHECK_RETURN_VALUE(p_Dtsec, E_INVALID_HANDLE, 0);203SANITY_CHECK_RETURN_VALUE(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE, 0);204205return fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap);206}207208/* .............................................................................. */209210static void DtsecIsr(t_Handle h_Dtsec)211{212t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;213uint32_t event;214struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;215216/* do not handle MDIO events */217event = fman_dtsec_get_event(p_DtsecMemMap, (uint32_t)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN)));218219event &= fman_dtsec_get_interrupt_mask(p_DtsecMemMap);220221fman_dtsec_ack_event(p_DtsecMemMap, event);222223if (event & DTSEC_IMASK_BREN)224p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_RX);225if (event & DTSEC_IMASK_RXCEN)226p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_CTL);227if (event & DTSEC_IMASK_MSROEN)228UpdateStatistics(p_Dtsec);229if (event & DTSEC_IMASK_GTSCEN)230p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET);231if (event & DTSEC_IMASK_BTEN)232p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_TX);233if (event & DTSEC_IMASK_TXCEN)234p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_CTL);235if (event & DTSEC_IMASK_TXEEN)236p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_ERR);237if (event & DTSEC_IMASK_LCEN)238p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_LATE_COL);239if (event & DTSEC_IMASK_CRLEN)240p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_COL_RET_LMT);241if (event & DTSEC_IMASK_XFUNEN)242{243#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6244if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)245{246uint32_t tpkt1, tmpReg1, tpkt2, tmpReg2, i;247/* a. Write 0x00E0_0C00 to DTSEC_ID */248/* This is a read only regidter */249250/* b. Read and save the value of TPKT */251tpkt1 = GET_UINT32(p_DtsecMemMap->tpkt);252253/* c. Read the register at dTSEC address offset 0x32C */254tmpReg1 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));255256/* d. Compare bits [9:15] to bits [25:31] of the register at address offset 0x32C. */257if ((tmpReg1 & 0x007F0000) != (tmpReg1 & 0x0000007F))258{259/* If they are not equal, save the value of this register and wait for at least260* MAXFRM*16 ns */261XX_UDelay((uint32_t)(MIN(DtsecGetMaxFrameLength(p_Dtsec)*16/1000, 1)));262}263264/* e. Read and save TPKT again and read the register at dTSEC address offset2650x32C again*/266tpkt2 = GET_UINT32(p_DtsecMemMap->tpkt);267tmpReg2 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));268269/* f. Compare the value of TPKT saved in step b to value read in step e. Also270compare bits [9:15] of the register at offset 0x32C saved in step d to the value271of bits [9:15] saved in step e. If the two registers values are unchanged, then272the transmit portion of the dTSEC controller is locked up and the user should273proceed to the recover sequence. */274if ((tpkt1 == tpkt2) && ((tmpReg1 & 0x007F0000) == (tmpReg2 & 0x007F0000)))275{276/* recover sequence */277278/* a.Write a 1 to RCTRL[GRS]*/279280WRITE_UINT32(p_DtsecMemMap->rctrl, GET_UINT32(p_DtsecMemMap->rctrl) | RCTRL_GRS);281282/* b.Wait until IEVENT[GRSC]=1, or at least 100 us has elapsed. */283for (i = 0 ; i < 100 ; i++ )284{285if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)286break;287XX_UDelay(1);288}289if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)290WRITE_UINT32(p_DtsecMemMap->ievent, DTSEC_IMASK_GRSCEN);291else292DBG(INFO,("Rx lockup due to dTSEC Tx lockup"));293294/* c.Write a 1 to bit n of FM_RSTC (offset 0x0CC of FPM)*/295FmResetMac(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G, p_Dtsec->fmMacControllerDriver.macId);296297/* d.Wait 4 Tx clocks (32 ns) */298XX_UDelay(1);299300/* e.Write a 0 to bit n of FM_RSTC. */301/* cleared by FMAN */302}303}304#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */305306p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_FIFO_UNDRN);307}308if (event & DTSEC_IMASK_MAGEN)309p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_MAG_PCKT);310if (event & DTSEC_IMASK_GRSCEN)311p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET);312if (event & DTSEC_IMASK_TDPEEN)313p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_DATA_ERR);314if (event & DTSEC_IMASK_RDPEEN)315p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_DATA_ERR);316317/* - masked interrupts */318ASSERT_COND(!(event & DTSEC_IMASK_ABRTEN));319ASSERT_COND(!(event & DTSEC_IMASK_IFERREN));320}321322static void DtsecMdioIsr(t_Handle h_Dtsec)323{324t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;325uint32_t event;326struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;327328event = GET_UINT32(p_DtsecMemMap->ievent);329/* handle only MDIO events */330event &= (DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN);331if (event)332{333event &= GET_UINT32(p_DtsecMemMap->imask);334335WRITE_UINT32(p_DtsecMemMap->ievent, event);336337if (event & DTSEC_IMASK_MMRDEN)338p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET);339if (event & DTSEC_IMASK_MMWREN)340p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET);341}342}343344static void Dtsec1588Isr(t_Handle h_Dtsec)345{346t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;347uint32_t event;348struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;349350if (p_Dtsec->ptpTsuEnabled)351{352event = fman_dtsec_check_and_clear_tmr_event(p_DtsecMemMap);353354if (event)355{356ASSERT_COND(event & TMR_PEVENT_TSRE);357p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_1588_TS_RX_ERR);358}359}360}361362/* ........................................................................... */363364static void FreeInitResources(t_Dtsec *p_Dtsec)365{366if (p_Dtsec->mdioIrq != NO_IRQ)367{368XX_DisableIntr(p_Dtsec->mdioIrq);369XX_FreeIntr(p_Dtsec->mdioIrq);370}371FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_ERR);372FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_NORMAL);373374/* release the driver's group hash table */375FreeHashTable(p_Dtsec->p_MulticastAddrHash);376p_Dtsec->p_MulticastAddrHash = NULL;377378/* release the driver's individual hash table */379FreeHashTable(p_Dtsec->p_UnicastAddrHash);380p_Dtsec->p_UnicastAddrHash = NULL;381}382383/* ........................................................................... */384385static t_Error GracefulStop(t_Dtsec *p_Dtsec, e_CommMode mode)386{387struct dtsec_regs *p_MemMap;388389ASSERT_COND(p_Dtsec);390391p_MemMap = p_Dtsec->p_MemMap;392ASSERT_COND(p_MemMap);393394/* Assert the graceful transmit stop bit */395if (mode & e_COMM_MODE_RX)396{397fman_dtsec_stop_rx(p_MemMap);398399#ifdef FM_GRS_ERRATA_DTSEC_A002400if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)401XX_UDelay(100);402#else /* FM_GRS_ERRATA_DTSEC_A002 */403#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839404XX_UDelay(10);405#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */406#endif /* FM_GRS_ERRATA_DTSEC_A002 */407}408409if (mode & e_COMM_MODE_TX)410#if defined(FM_GTS_ERRATA_DTSEC_A004) || defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012)411if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)412DBG(INFO, ("GTS not supported due to DTSEC_A004 errata."));413#else /* not defined(FM_GTS_ERRATA_DTSEC_A004) ||... */414#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014415DBG(INFO, ("GTS not supported due to DTSEC_A0014 errata."));416#else /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */417fman_dtsec_stop_tx(p_MemMap);418#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */419#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||... */420421return E_OK;422}423424/* .............................................................................. */425426static t_Error GracefulRestart(t_Dtsec *p_Dtsec, e_CommMode mode)427{428struct dtsec_regs *p_MemMap;429430ASSERT_COND(p_Dtsec);431p_MemMap = p_Dtsec->p_MemMap;432ASSERT_COND(p_MemMap);433434/* clear the graceful receive stop bit */435if (mode & e_COMM_MODE_TX)436fman_dtsec_start_tx(p_MemMap);437438if (mode & e_COMM_MODE_RX)439fman_dtsec_start_rx(p_MemMap);440441return E_OK;442}443444445/*****************************************************************************/446/* dTSEC Configs modification functions */447/*****************************************************************************/448449/* .............................................................................. */450451static t_Error DtsecConfigLoopback(t_Handle h_Dtsec, bool newVal)452{453454t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;455456SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);457SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);458459p_Dtsec->p_DtsecDriverParam->loopback = newVal;460461return E_OK;462}463464/* .............................................................................. */465466static t_Error DtsecConfigMaxFrameLength(t_Handle h_Dtsec, uint16_t newVal)467{468t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;469470SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);471SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);472473p_Dtsec->p_DtsecDriverParam->maximum_frame = newVal;474475return E_OK;476}477478/* .............................................................................. */479480static t_Error DtsecConfigPadAndCrc(t_Handle h_Dtsec, bool newVal)481{482t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;483484SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);485SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);486487p_Dtsec->p_DtsecDriverParam->tx_pad_crc = newVal;488489return E_OK;490}491492/* .............................................................................. */493494static t_Error DtsecConfigHalfDuplex(t_Handle h_Dtsec, bool newVal)495{496t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;497498SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);499SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);500501p_Dtsec->p_DtsecDriverParam->halfdup_on = newVal;502503return E_OK;504}505506/* .............................................................................. */507508static t_Error DtsecConfigTbiPhyAddr(t_Handle h_Dtsec, uint8_t newVal)509{510t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;511512SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);513SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);514515p_Dtsec->p_DtsecDriverParam->tbi_phy_addr = newVal;516517return E_OK;518}519520/* .............................................................................. */521522static t_Error DtsecConfigLengthCheck(t_Handle h_Dtsec, bool newVal)523{524t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;525526SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);527SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);528529p_Dtsec->p_DtsecDriverParam->rx_len_check = newVal;530531return E_OK;532}533534/* .............................................................................. */535536static t_Error DtsecConfigException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)537{538t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;539uint32_t bitMask = 0;540541SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);542SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);543544if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)545{546GET_EXCEPTION_FLAG(bitMask, exception);547if (bitMask)548{549if (enable)550p_Dtsec->exceptions |= bitMask;551else552p_Dtsec->exceptions &= ~bitMask;553}554else555RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));556}557else558{559if (!p_Dtsec->ptpTsuEnabled)560RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));561562if (enable)563p_Dtsec->enTsuErrExeption = TRUE;564else565p_Dtsec->enTsuErrExeption = FALSE;566}567568return E_OK;569}570571572/*****************************************************************************/573/* dTSEC Run Time API functions */574/*****************************************************************************/575576/* .............................................................................. */577578static t_Error DtsecEnable(t_Handle h_Dtsec, e_CommMode mode)579{580t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;581582SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);583SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);584585fman_dtsec_enable(p_Dtsec->p_MemMap,586(bool)!!(mode & e_COMM_MODE_RX),587(bool)!!(mode & e_COMM_MODE_TX));588589GracefulRestart(p_Dtsec, mode);590591return E_OK;592}593594/* .............................................................................. */595596static t_Error DtsecDisable (t_Handle h_Dtsec, e_CommMode mode)597{598t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;599600SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);601SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);602603GracefulStop(p_Dtsec, mode);604605fman_dtsec_disable(p_Dtsec->p_MemMap,606(bool)!!(mode & e_COMM_MODE_RX),607(bool)!!(mode & e_COMM_MODE_TX));608609return E_OK;610}611612/* .............................................................................. */613614static t_Error DtsecSetTxPauseFrames(t_Handle h_Dtsec,615uint8_t priority,616uint16_t pauseTime,617uint16_t threshTime)618{619t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;620621UNUSED(priority);UNUSED(threshTime);622623SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);624SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);625626#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003627if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)628if (0 < pauseTime && pauseTime <= 320)629RETURN_ERROR(MINOR, E_INVALID_VALUE,630("This pause-time value of %d is illegal due to errata dTSEC-A003!"631" value should be greater than 320."));632#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */633634fman_dtsec_set_tx_pause_frames(p_Dtsec->p_MemMap, pauseTime);635return E_OK;636}637638/* .............................................................................. */639/* backward compatibility. will be removed in the future. */640static t_Error DtsecTxMacPause(t_Handle h_Dtsec, uint16_t pauseTime)641{642return DtsecSetTxPauseFrames(h_Dtsec, 0, pauseTime, 0);643}644645/* .............................................................................. */646647static t_Error DtsecRxIgnoreMacPause(t_Handle h_Dtsec, bool en)648{649t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;650bool accept_pause = !en;651652SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);653SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);654655fman_dtsec_handle_rx_pause(p_Dtsec->p_MemMap, accept_pause);656657return E_OK;658}659660/* .............................................................................. */661662static t_Error DtsecEnable1588TimeStamp(t_Handle h_Dtsec)663{664t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;665666SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);667SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);668669p_Dtsec->ptpTsuEnabled = TRUE;670fman_dtsec_set_ts(p_Dtsec->p_MemMap, TRUE);671672return E_OK;673}674675/* .............................................................................. */676677static t_Error DtsecDisable1588TimeStamp(t_Handle h_Dtsec)678{679t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;680681SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);682SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);683684p_Dtsec->ptpTsuEnabled = FALSE;685fman_dtsec_set_ts(p_Dtsec->p_MemMap, FALSE);686687return E_OK;688}689690/* .............................................................................. */691692static t_Error DtsecGetStatistics(t_Handle h_Dtsec, t_FmMacStatistics *p_Statistics)693{694t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;695struct dtsec_regs *p_DtsecMemMap;696697SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);698SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);699SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);700701p_DtsecMemMap = p_Dtsec->p_MemMap;702703if (p_Dtsec->statisticsLevel == e_FM_MAC_NONE_STATISTICS)704RETURN_ERROR(MINOR, E_INVALID_STATE, ("Statistics disabled"));705706memset(p_Statistics, 0xff, sizeof(t_FmMacStatistics));707708if (p_Dtsec->statisticsLevel == e_FM_MAC_FULL_STATISTICS)709{710p_Statistics->eStatPkts64 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR64)711+ p_Dtsec->internalStatistics.tr64;712p_Statistics->eStatPkts65to127 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR127)713+ p_Dtsec->internalStatistics.tr127;714p_Statistics->eStatPkts128to255 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR255)715+ p_Dtsec->internalStatistics.tr255;716p_Statistics->eStatPkts256to511 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR511)717+ p_Dtsec->internalStatistics.tr511;718p_Statistics->eStatPkts512to1023 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR1K)719+ p_Dtsec->internalStatistics.tr1k;720p_Statistics->eStatPkts1024to1518 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMAX)721+ p_Dtsec->internalStatistics.trmax;722p_Statistics->eStatPkts1519to1522 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMGV)723+ p_Dtsec->internalStatistics.trmgv;724725/* MIB II */726p_Statistics->ifInOctets = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBYT)727+ p_Dtsec->internalStatistics.rbyt;728p_Statistics->ifInPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RPKT)729+ p_Dtsec->internalStatistics.rpkt;730p_Statistics->ifInUcastPkts = 0;731p_Statistics->ifInMcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RMCA)732+ p_Dtsec->internalStatistics.rmca;733p_Statistics->ifInBcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBCA)734+ p_Dtsec->internalStatistics.rbca;735p_Statistics->ifOutOctets = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBYT)736+ p_Dtsec->internalStatistics.tbyt;737p_Statistics->ifOutPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TPKT)738+ p_Dtsec->internalStatistics.tpkt;739p_Statistics->ifOutUcastPkts = 0;740p_Statistics->ifOutMcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TMCA)741+ p_Dtsec->internalStatistics.tmca;742p_Statistics->ifOutBcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBCA)743+ p_Dtsec->internalStatistics.tbca;744}745746p_Statistics->eStatFragments = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RFRG)747+ p_Dtsec->internalStatistics.rfrg;748p_Statistics->eStatJabbers = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RJBR)749+ p_Dtsec->internalStatistics.rjbr;750p_Statistics->eStatsDropEvents = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RDRP)751+ p_Dtsec->internalStatistics.rdrp;752p_Statistics->eStatCRCAlignErrors = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RALN)753+ p_Dtsec->internalStatistics.raln;754p_Statistics->eStatUndersizePkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RUND)755+ p_Dtsec->internalStatistics.rund;756p_Statistics->eStatOversizePkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_ROVR)757+ p_Dtsec->internalStatistics.rovr;758p_Statistics->reStatPause = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RXPF)759+ p_Dtsec->internalStatistics.rxpf;760p_Statistics->teStatPause = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TXPF)761+ p_Dtsec->internalStatistics.txpf;762p_Statistics->ifInDiscards = p_Statistics->eStatsDropEvents;763p_Statistics->ifInErrors = p_Statistics->eStatsDropEvents + p_Statistics->eStatCRCAlignErrors764+ fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RFLR) + p_Dtsec->internalStatistics.rflr765+ fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCDE) + p_Dtsec->internalStatistics.rcde766+ fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCSE) + p_Dtsec->internalStatistics.rcse;767768p_Statistics->ifOutDiscards = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TDRP)769+ p_Dtsec->internalStatistics.tdrp;770p_Statistics->ifOutErrors = p_Statistics->ifOutDiscards /**< Number of frames transmitted with error: */771+ fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_TFCS)772+ p_Dtsec->internalStatistics.tfcs;773774return E_OK;775}776777/* .............................................................................. */778779static t_Error DtsecModifyMacAddress (t_Handle h_Dtsec, t_EnetAddr *p_EnetAddr)780{781t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;782783SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);784SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);785786/* Initialize MAC Station Address registers (1 & 2) */787/* Station address have to be swapped (big endian to little endian */788p_Dtsec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr);789fman_dtsec_set_mac_address(p_Dtsec->p_MemMap, (uint8_t *)(*p_EnetAddr));790791return E_OK;792}793794/* .............................................................................. */795796static t_Error DtsecResetCounters (t_Handle h_Dtsec)797{798t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;799800SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);801SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);802803/* clear HW counters */804fman_dtsec_reset_stat(p_Dtsec->p_MemMap);805806/* clear SW counters holding carries */807memset(&p_Dtsec->internalStatistics, 0, sizeof(t_InternalStatistics));808809return E_OK;810}811812/* .............................................................................. */813814static t_Error DtsecAddExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)815{816t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec;817uint64_t ethAddr;818uint8_t paddrNum;819820SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);821SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);822823ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);824825if (ethAddr & GROUP_ADDRESS)826/* Multicast address has no effect in PADDR */827RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));828829/* Make sure no PADDR contains this address */830for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)831if (p_Dtsec->indAddrRegUsed[paddrNum])832if (p_Dtsec->paddr[paddrNum] == ethAddr)833RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);834835/* Find first unused PADDR */836for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)837if (!(p_Dtsec->indAddrRegUsed[paddrNum]))838{839/* mark this PADDR as used */840p_Dtsec->indAddrRegUsed[paddrNum] = TRUE;841/* store address */842p_Dtsec->paddr[paddrNum] = ethAddr;843844/* put in hardware */845fman_dtsec_add_addr_in_paddr(p_Dtsec->p_MemMap, (uint64_t)PTR_TO_UINT(ðAddr), paddrNum);846p_Dtsec->numOfIndAddrInRegs++;847848return E_OK;849}850851/* No free PADDR */852RETURN_ERROR(MAJOR, E_FULL, NO_MSG);853}854855/* .............................................................................. */856857static t_Error DtsecDelExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)858{859t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec;860uint64_t ethAddr;861uint8_t paddrNum;862863SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);864SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);865866ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);867868/* Find used PADDR containing this address */869for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)870{871if ((p_Dtsec->indAddrRegUsed[paddrNum]) &&872(p_Dtsec->paddr[paddrNum] == ethAddr))873{874/* mark this PADDR as not used */875p_Dtsec->indAddrRegUsed[paddrNum] = FALSE;876/* clear in hardware */877fman_dtsec_clear_addr_in_paddr(p_Dtsec->p_MemMap, paddrNum);878p_Dtsec->numOfIndAddrInRegs--;879880return E_OK;881}882}883884RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);885}886887/* .............................................................................. */888889static t_Error DtsecAddHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)890{891t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;892t_EthHashEntry *p_HashEntry;893uint64_t ethAddr;894int32_t bucket;895uint32_t crc;896bool mcast, ghtx;897898SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);899SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);900901ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);902903ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);904mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);905906if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */907RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket"));908909crc = GetMacAddrHashCode(ethAddr);910911/* considering the 9 highest order bits in crc H[8:0]:912* if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register913* and H[5:1] (next 5 bits) identify the hash bit914* if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register915* and H[4:0] (next 5 bits) identify the hash bit.916*917* In bucket index output the low 5 bits identify the hash register bit,918* while the higher 4 bits identify the hash register919*/920921if (ghtx)922bucket = (int32_t)((crc >> 23) & 0x1ff);923else {924bucket = (int32_t)((crc >> 24) & 0xff);925/* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */926if (mcast)927bucket += 0x100;928}929930fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, TRUE);931932/* Create element to be added to the driver hash table */933p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry));934p_HashEntry->addr = ethAddr;935INIT_LIST(&p_HashEntry->node);936937if (ethAddr & MAC_GROUP_ADDRESS)938/* Group Address */939NCSW_LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]));940else941NCSW_LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]));942943return E_OK;944}945946/* .............................................................................. */947948static t_Error DtsecDelHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)949{950t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;951t_List *p_Pos;952t_EthHashEntry *p_HashEntry = NULL;953uint64_t ethAddr;954int32_t bucket;955uint32_t crc;956bool mcast, ghtx;957958SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);959SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);960961ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);962963ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);964mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);965966if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */967RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket"));968969crc = GetMacAddrHashCode(ethAddr);970971if (ghtx)972bucket = (int32_t)((crc >> 23) & 0x1ff);973else {974bucket = (int32_t)((crc >> 24) & 0xff);975/* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */976if (mcast)977bucket += 0x100;978}979980if (ethAddr & MAC_GROUP_ADDRESS)981{982/* Group Address */983NCSW_LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))984{985p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);986if (p_HashEntry->addr == ethAddr)987{988NCSW_LIST_DelAndInit(&p_HashEntry->node);989XX_Free(p_HashEntry);990break;991}992}993if (NCSW_LIST_IsEmpty(&p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))994fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);995}996else997{998/* Individual Address */999NCSW_LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))1000{1001p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);1002if (p_HashEntry->addr == ethAddr)1003{1004NCSW_LIST_DelAndInit(&p_HashEntry->node);1005XX_Free(p_HashEntry);1006break;1007}1008}1009if (NCSW_LIST_IsEmpty(&p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))1010fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);1011}10121013/* address does not exist */1014ASSERT_COND(p_HashEntry != NULL);10151016return E_OK;1017}10181019/* .............................................................................. */10201021static t_Error DtsecSetPromiscuous(t_Handle h_Dtsec, bool newVal)1022{1023t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;10241025SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);1026SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);10271028fman_dtsec_set_uc_promisc(p_Dtsec->p_MemMap, newVal);1029fman_dtsec_set_mc_promisc(p_Dtsec->p_MemMap, newVal);10301031return E_OK;1032}10331034/* .............................................................................. */10351036static t_Error DtsecSetStatistics(t_Handle h_Dtsec, e_FmMacStatisticsLevel statisticsLevel)1037{1038t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;1039t_Error err;10401041SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);1042SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);10431044p_Dtsec->statisticsLevel = statisticsLevel;10451046err = (t_Error)fman_dtsec_set_stat_level(p_Dtsec->p_MemMap,1047(enum dtsec_stat_level)statisticsLevel);1048if (err != E_OK)1049return err;10501051switch (statisticsLevel)1052{1053case (e_FM_MAC_NONE_STATISTICS):1054p_Dtsec->exceptions &= ~DTSEC_IMASK_MSROEN;1055break;1056case (e_FM_MAC_PARTIAL_STATISTICS):1057p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;1058break;1059case (e_FM_MAC_FULL_STATISTICS):1060p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;1061break;1062default:1063RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);1064}10651066return E_OK;1067}10681069/* .............................................................................. */10701071static t_Error DtsecSetWakeOnLan(t_Handle h_Dtsec, bool en)1072{1073t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;10741075SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);1076SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);10771078fman_dtsec_set_wol(p_Dtsec->p_MemMap, en);10791080return E_OK;1081}10821083/* .............................................................................. */10841085static t_Error DtsecAdjustLink(t_Handle h_Dtsec, e_EnetSpeed speed, bool fullDuplex)1086{1087t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;1088int err;1089enum enet_interface enet_interface;1090enum enet_speed enet_speed;10911092SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);1093SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);10941095p_Dtsec->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode), speed);1096enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode);1097enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Dtsec->enetMode);1098p_Dtsec->halfDuplex = !fullDuplex;10991100err = fman_dtsec_adjust_link(p_Dtsec->p_MemMap, enet_interface, enet_speed, fullDuplex);11011102if (err == -EINVAL)1103RETURN_ERROR(MAJOR, E_CONFLICT, ("Ethernet interface does not support Half Duplex mode"));11041105return (t_Error)err;1106}11071108/* .............................................................................. */11091110static t_Error DtsecRestartAutoneg(t_Handle h_Dtsec)1111{1112t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;1113uint16_t tmpReg16;11141115SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);1116SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);11171118DTSEC_MII_ReadPhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, &tmpReg16);11191120tmpReg16 &= ~( PHY_CR_SPEED0 | PHY_CR_SPEED1 );1121tmpReg16 |= (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);11221123DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, tmpReg16);11241125return E_OK;1126}11271128/* .............................................................................. */11291130static t_Error DtsecGetId(t_Handle h_Dtsec, uint32_t *macId)1131{1132t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;11331134SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);1135SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);11361137*macId = p_Dtsec->macId;11381139return E_OK;1140}11411142/* .............................................................................. */11431144static t_Error DtsecGetVersion(t_Handle h_Dtsec, uint32_t *macVersion)1145{1146t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;11471148SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);1149SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);11501151*macVersion = fman_dtsec_get_revision(p_Dtsec->p_MemMap);11521153return E_OK;1154}11551156/* .............................................................................. */11571158static t_Error DtsecSetException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)1159{1160t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;1161uint32_t bitMask = 0;11621163SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);1164SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);11651166if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)1167{1168GET_EXCEPTION_FLAG(bitMask, exception);1169if (bitMask)1170{1171if (enable)1172p_Dtsec->exceptions |= bitMask;1173else1174p_Dtsec->exceptions &= ~bitMask;1175}1176else1177RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));11781179if (enable)1180fman_dtsec_enable_interrupt(p_Dtsec->p_MemMap, bitMask);1181else1182fman_dtsec_disable_interrupt(p_Dtsec->p_MemMap, bitMask);1183}1184else1185{1186if (!p_Dtsec->ptpTsuEnabled)1187RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));11881189if (enable)1190{1191p_Dtsec->enTsuErrExeption = TRUE;1192fman_dtsec_enable_tmr_interrupt(p_Dtsec->p_MemMap);1193}1194else1195{1196p_Dtsec->enTsuErrExeption = FALSE;1197fman_dtsec_disable_tmr_interrupt(p_Dtsec->p_MemMap);1198}1199}12001201return E_OK;1202}120312041205/*****************************************************************************/1206/* dTSEC Init & Free API */1207/*****************************************************************************/12081209/* .............................................................................. */12101211static t_Error DtsecInit(t_Handle h_Dtsec)1212{1213t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;1214struct dtsec_cfg *p_DtsecDriverParam;1215t_Error err;1216uint16_t maxFrmLn;1217enum enet_interface enet_interface;1218enum enet_speed enet_speed;1219t_EnetAddr ethAddr;12201221SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);1222SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);1223SANITY_CHECK_RETURN_ERROR(p_Dtsec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);12241225FM_GetRevision(p_Dtsec->fmMacControllerDriver.h_Fm, &p_Dtsec->fmMacControllerDriver.fmRevInfo);1226CHECK_INIT_PARAMETERS(p_Dtsec, CheckInitParameters);12271228p_DtsecDriverParam = p_Dtsec->p_DtsecDriverParam;1229p_Dtsec->halfDuplex = p_DtsecDriverParam->halfdup_on;12301231enet_interface = (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode);1232enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_Dtsec->enetMode);1233MAKE_ENET_ADDR_FROM_UINT64(p_Dtsec->addr, ethAddr);12341235err = (t_Error)fman_dtsec_init(p_Dtsec->p_MemMap,1236p_DtsecDriverParam,1237enet_interface,1238enet_speed,1239(uint8_t*)ethAddr,1240p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev,1241p_Dtsec->fmMacControllerDriver.fmRevInfo.minorRev,1242p_Dtsec->exceptions);1243if (err)1244{1245FreeInitResources(p_Dtsec);1246RETURN_ERROR(MAJOR, err, ("This DTSEC version does not support the required i/f mode"));1247}12481249if (ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode) == e_ENET_IF_SGMII)1250{1251uint16_t tmpReg16;12521253/* Configure the TBI PHY Control Register */1254tmpReg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET;1255DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);12561257tmpReg16 = PHY_TBICON_CLK_SEL;1258DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);12591260tmpReg16 = (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);1261DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);12621263if (p_Dtsec->enetMode & ENET_IF_SGMII_BASEX)1264tmpReg16 = PHY_TBIANA_1000X;1265else1266tmpReg16 = PHY_TBIANA_SGMII;1267DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 4, tmpReg16);12681269tmpReg16 = (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);12701271DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);1272}12731274/* Max Frame Length */1275maxFrmLn = fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap);1276err = FmSetMacMaxFrame(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G,1277p_Dtsec->fmMacControllerDriver.macId, maxFrmLn);1278if (err)1279RETURN_ERROR(MINOR,err, NO_MSG);12801281p_Dtsec->p_MulticastAddrHash = AllocHashTable(EXTENDED_HASH_TABLE_SIZE);1282if (!p_Dtsec->p_MulticastAddrHash) {1283FreeInitResources(p_Dtsec);1284RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MC hash table is FAILED"));1285}12861287p_Dtsec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);1288if (!p_Dtsec->p_UnicastAddrHash)1289{1290FreeInitResources(p_Dtsec);1291RETURN_ERROR(MAJOR, E_NO_MEMORY, ("UC hash table is FAILED"));1292}12931294/* register err intr handler for dtsec to FPM (err)*/1295FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,1296e_FM_MOD_1G_MAC,1297p_Dtsec->macId,1298e_FM_INTR_TYPE_ERR,1299DtsecIsr,1300p_Dtsec);1301/* register 1588 intr handler for TMR to FPM (normal)*/1302FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,1303e_FM_MOD_1G_MAC,1304p_Dtsec->macId,1305e_FM_INTR_TYPE_NORMAL,1306Dtsec1588Isr,1307p_Dtsec);1308/* register normal intr handler for dtsec to main interrupt controller. */1309if (p_Dtsec->mdioIrq != NO_IRQ)1310{1311XX_SetIntr(p_Dtsec->mdioIrq, DtsecMdioIsr, p_Dtsec);1312XX_EnableIntr(p_Dtsec->mdioIrq);1313}13141315XX_Free(p_DtsecDriverParam);1316p_Dtsec->p_DtsecDriverParam = NULL;13171318err = DtsecSetStatistics(h_Dtsec, e_FM_MAC_FULL_STATISTICS);1319if (err)1320{1321FreeInitResources(p_Dtsec);1322RETURN_ERROR(MAJOR, err, ("Undefined statistics level"));1323}13241325return E_OK;1326}13271328/* ........................................................................... */13291330static t_Error DtsecFree(t_Handle h_Dtsec)1331{1332t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;13331334SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);13351336if (p_Dtsec->p_DtsecDriverParam)1337{1338/* Called after config */1339XX_Free(p_Dtsec->p_DtsecDriverParam);1340p_Dtsec->p_DtsecDriverParam = NULL;1341}1342else1343/* Called after init */1344FreeInitResources(p_Dtsec);13451346XX_Free(p_Dtsec);13471348return E_OK;1349}13501351/* .............................................................................. */13521353static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)1354{1355p_FmMacControllerDriver->f_FM_MAC_Init = DtsecInit;1356p_FmMacControllerDriver->f_FM_MAC_Free = DtsecFree;13571358p_FmMacControllerDriver->f_FM_MAC_SetStatistics = DtsecSetStatistics;1359p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = DtsecConfigLoopback;1360p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = DtsecConfigMaxFrameLength;13611362p_FmMacControllerDriver->f_FM_MAC_ConfigWan = NULL; /* Not supported on dTSEC */13631364p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc = DtsecConfigPadAndCrc;1365p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex = DtsecConfigHalfDuplex;1366p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck = DtsecConfigLengthCheck;1367p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr = DtsecConfigTbiPhyAddr;1368p_FmMacControllerDriver->f_FM_MAC_ConfigException = DtsecConfigException;1369p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit = NULL;13701371p_FmMacControllerDriver->f_FM_MAC_Enable = DtsecEnable;1372p_FmMacControllerDriver->f_FM_MAC_Disable = DtsecDisable;1373p_FmMacControllerDriver->f_FM_MAC_Resume = NULL;13741375p_FmMacControllerDriver->f_FM_MAC_SetException = DtsecSetException;13761377p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous = DtsecSetPromiscuous;1378p_FmMacControllerDriver->f_FM_MAC_AdjustLink = DtsecAdjustLink;1379p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan = DtsecSetWakeOnLan;1380p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg = DtsecRestartAutoneg;13811382p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = DtsecEnable1588TimeStamp;1383p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = DtsecDisable1588TimeStamp;13841385p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = DtsecTxMacPause;1386p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = DtsecSetTxPauseFrames;1387p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = DtsecRxIgnoreMacPause;13881389p_FmMacControllerDriver->f_FM_MAC_ResetCounters = DtsecResetCounters;1390p_FmMacControllerDriver->f_FM_MAC_GetStatistics = DtsecGetStatistics;13911392p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr = DtsecModifyMacAddress;1393p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr = DtsecAddHashMacAddress;1394p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr = DtsecDelHashMacAddress;1395p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr = DtsecAddExactMatchMacAddress;1396p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr = DtsecDelExactMatchMacAddress;1397p_FmMacControllerDriver->f_FM_MAC_GetId = DtsecGetId;1398p_FmMacControllerDriver->f_FM_MAC_GetVersion = DtsecGetVersion;1399p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength = DtsecGetMaxFrameLength;14001401p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = DTSEC_MII_WritePhyReg;1402p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = DTSEC_MII_ReadPhyReg;14031404}140514061407/*****************************************************************************/1408/* dTSEC Config Main Entry */1409/*****************************************************************************/14101411/* .............................................................................. */14121413t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam)1414{1415t_Dtsec *p_Dtsec;1416struct dtsec_cfg *p_DtsecDriverParam;1417uintptr_t baseAddr;14181419SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);14201421baseAddr = p_FmMacParam->baseAddr;14221423/* allocate memory for the UCC GETH data structure. */1424p_Dtsec = (t_Dtsec *)XX_Malloc(sizeof(t_Dtsec));1425if (!p_Dtsec)1426{1427REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver structure"));1428return NULL;1429}1430memset(p_Dtsec, 0, sizeof(t_Dtsec));1431InitFmMacControllerDriver(&p_Dtsec->fmMacControllerDriver);14321433/* allocate memory for the dTSEC driver parameters data structure. */1434p_DtsecDriverParam = (struct dtsec_cfg *) XX_Malloc(sizeof(struct dtsec_cfg));1435if (!p_DtsecDriverParam)1436{1437XX_Free(p_Dtsec);1438REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver parameters"));1439return NULL;1440}1441memset(p_DtsecDriverParam, 0, sizeof(struct dtsec_cfg));14421443/* Plant parameter structure pointer */1444p_Dtsec->p_DtsecDriverParam = p_DtsecDriverParam;14451446fman_dtsec_defconfig(p_DtsecDriverParam);14471448p_Dtsec->p_MemMap = (struct dtsec_regs *)UINT_TO_PTR(baseAddr);1449p_Dtsec->p_MiiMemMap = (struct dtsec_mii_reg *)UINT_TO_PTR(baseAddr + DTSEC_TO_MII_OFFSET);1450p_Dtsec->addr = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);1451p_Dtsec->enetMode = p_FmMacParam->enetMode;1452p_Dtsec->macId = p_FmMacParam->macId;1453p_Dtsec->exceptions = DEFAULT_exceptions;1454p_Dtsec->mdioIrq = p_FmMacParam->mdioIrq;1455p_Dtsec->f_Exception = p_FmMacParam->f_Exception;1456p_Dtsec->f_Event = p_FmMacParam->f_Event;1457p_Dtsec->h_App = p_FmMacParam->h_App;1458p_Dtsec->ptpTsuEnabled = p_Dtsec->p_DtsecDriverParam->ptp_tsu_en;1459p_Dtsec->enTsuErrExeption = p_Dtsec->p_DtsecDriverParam->ptp_exception_en;1460p_Dtsec->tbi_phy_addr = p_Dtsec->p_DtsecDriverParam->tbi_phy_addr;14611462return p_Dtsec;1463}146414651466