1/*
2 * Copyright 2008-2013 Freescale Semiconductor Inc.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *     * Redistributions of source code must retain the above copyright
7 *       notice, this list of conditions and the following disclaimer.
8 *     * Redistributions in binary form must reproduce the above copyright
9 *       notice, this list of conditions and the following disclaimer in the
10 *       documentation and/or other materials provided with the distribution.
11 *     * Neither the name of Freescale Semiconductor nor the
12 *       names of its contributors may be used to endorse or promote products
13 *       derived from this software without specific prior written permission.
14 *
15 *
16 * ALTERNATIVELY, this software may be distributed under the terms of the
17 * GNU General Public License ("GPL") as published by the Free Software
18 * Foundation, either version 2 of that License or (at your option) any
19 * later version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
22 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33/******************************************************************************
34 @File          dtsec.c
35
36 @Description   FMan dTSEC driver
37*//***************************************************************************/
38
39#include "std_ext.h"
40#include "error_ext.h"
41#include "string_ext.h"
42#include "xx_ext.h"
43#include "endian_ext.h"
44#include "debug_ext.h"
45#include "crc_mac_addr_ext.h"
46
47#include "fm_common.h"
48#include "dtsec.h"
49#include "fsl_fman_dtsec.h"
50#include "fsl_fman_dtsec_mii_acc.h"
51
52/*****************************************************************************/
53/*                      Internal routines                                    */
54/*****************************************************************************/
55
56static t_Error CheckInitParameters(t_Dtsec *p_Dtsec)
57{
58    if (ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_10000)
59        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet 1G MAC driver only supports 1G or lower speeds"));
60    if (p_Dtsec->macId >= FM_MAX_NUM_OF_1G_MACS)
61        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("macId can not be greater than the number of 1G MACs"));
62    if (p_Dtsec->addr == 0)
63        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC Must have a valid MAC Address"));
64    if ((ENET_SPEED_FROM_MODE(p_Dtsec->enetMode) >= e_ENET_SPEED_1000) &&
65        p_Dtsec->p_DtsecDriverParam->halfdup_on)
66        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Ethernet MAC 1G can't work in half duplex"));
67    if (p_Dtsec->p_DtsecDriverParam->halfdup_on && (p_Dtsec->p_DtsecDriverParam)->loopback)
68        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("LoopBack is not supported in halfDuplex mode"));
69#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A001
70    if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev <= 6) /* fixed for rev3 */
71        if (p_Dtsec->p_DtsecDriverParam->rx_preamble)
72            RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("preambleRxEn"));
73#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */
74    if (((p_Dtsec->p_DtsecDriverParam)->tx_preamble || (p_Dtsec->p_DtsecDriverParam)->rx_preamble) &&( (p_Dtsec->p_DtsecDriverParam)->preamble_len != 0x7))
75        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Preamble length should be 0x7 bytes"));
76    if ((p_Dtsec->p_DtsecDriverParam)->halfdup_on &&
77       (p_Dtsec->p_DtsecDriverParam->tx_time_stamp_en || p_Dtsec->p_DtsecDriverParam->rx_time_stamp_en))
78        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dTSEC in half duplex mode has to be with 1588 timeStamping diable"));
79    if ((p_Dtsec->p_DtsecDriverParam)->rx_flow && (p_Dtsec->p_DtsecDriverParam)->rx_ctrl_acc )
80        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Receive control frame are not passed to the system memory so it can not be accept "));
81    if ((p_Dtsec->p_DtsecDriverParam)->rx_prepend  > MAX_PACKET_ALIGNMENT)
82        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("packetAlignmentPadding can't be greater than %d ",MAX_PACKET_ALIGNMENT ));
83    if (((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg1  > MAX_INTER_PACKET_GAP) ||
84        ((p_Dtsec->p_DtsecDriverParam)->non_back_to_back_ipg2 > MAX_INTER_PACKET_GAP) ||
85        ((p_Dtsec->p_DtsecDriverParam)->back_to_back_ipg > MAX_INTER_PACKET_GAP))
86        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Inter packet gap can't be greater than %d ",MAX_INTER_PACKET_GAP ));
87    if ((p_Dtsec->p_DtsecDriverParam)->halfdup_alt_backoff_val > MAX_INTER_PALTERNATE_BEB)
88        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("alternateBackoffVal can't be greater than %d ",MAX_INTER_PALTERNATE_BEB ));
89    if ((p_Dtsec->p_DtsecDriverParam)->halfdup_retransmit > MAX_RETRANSMISSION)
90        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("maxRetransmission can't be greater than %d ",MAX_RETRANSMISSION ));
91    if ((p_Dtsec->p_DtsecDriverParam)->halfdup_coll_window > MAX_COLLISION_WINDOW)
92        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("collisionWindow can't be greater than %d ",MAX_COLLISION_WINDOW ));
93
94    /*  If Auto negotiation process is disabled, need to */
95    /*  Set up the PHY using the MII Management Interface */
96    if (p_Dtsec->p_DtsecDriverParam->tbipa > MAX_PHYS)
97        RETURN_ERROR(MAJOR, E_NOT_IN_RANGE, ("PHY address (should be 0-%d)", MAX_PHYS));
98    if (!p_Dtsec->f_Exception)
99        RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Exception"));
100    if (!p_Dtsec->f_Event)
101        RETURN_ERROR(MAJOR, E_INVALID_HANDLE, ("uninitialized f_Event"));
102
103#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
104    if (p_Dtsec->p_DtsecDriverParam->rx_len_check)
105       RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("LengthCheck!"));
106#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
107
108    return E_OK;
109}
110
111/* ......................................................................... */
112
113static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
114{
115    uint32_t crc;
116
117    /* CRC calculation */
118    GET_MAC_ADDR_CRC(ethAddr, crc);
119
120    crc = GetMirror32(crc);
121
122    return crc;
123}
124
125/* ......................................................................... */
126
127static void UpdateStatistics(t_Dtsec *p_Dtsec)
128{
129    uint32_t car1, car2;
130
131    fman_dtsec_get_clear_carry_regs(p_Dtsec->p_MemMap, &car1, &car2);
132
133    if (car1)
134    {
135        if (car1 & CAR1_TR64)
136            p_Dtsec->internalStatistics.tr64 += VAL22BIT;
137        if (car1 & CAR1_TR127)
138            p_Dtsec->internalStatistics.tr127 += VAL22BIT;
139        if (car1 & CAR1_TR255)
140            p_Dtsec->internalStatistics.tr255 += VAL22BIT;
141        if (car1 & CAR1_TR511)
142            p_Dtsec->internalStatistics.tr511 += VAL22BIT;
143        if (car1 & CAR1_TRK1)
144            p_Dtsec->internalStatistics.tr1k += VAL22BIT;
145        if (car1 & CAR1_TRMAX)
146            p_Dtsec->internalStatistics.trmax += VAL22BIT;
147        if (car1 & CAR1_TRMGV)
148            p_Dtsec->internalStatistics.trmgv += VAL22BIT;
149        if (car1 & CAR1_RBYT)
150            p_Dtsec->internalStatistics.rbyt += (uint64_t)VAL32BIT;
151        if (car1 & CAR1_RPKT)
152            p_Dtsec->internalStatistics.rpkt += VAL22BIT;
153        if (car1 & CAR1_RMCA)
154            p_Dtsec->internalStatistics.rmca += VAL22BIT;
155        if (car1 & CAR1_RBCA)
156            p_Dtsec->internalStatistics.rbca += VAL22BIT;
157        if (car1 & CAR1_RXPF)
158            p_Dtsec->internalStatistics.rxpf += VAL16BIT;
159        if (car1 & CAR1_RALN)
160            p_Dtsec->internalStatistics.raln += VAL16BIT;
161        if (car1 & CAR1_RFLR)
162            p_Dtsec->internalStatistics.rflr += VAL16BIT;
163        if (car1 & CAR1_RCDE)
164            p_Dtsec->internalStatistics.rcde += VAL16BIT;
165        if (car1 & CAR1_RCSE)
166            p_Dtsec->internalStatistics.rcse += VAL16BIT;
167        if (car1 & CAR1_RUND)
168            p_Dtsec->internalStatistics.rund += VAL16BIT;
169        if (car1 & CAR1_ROVR)
170            p_Dtsec->internalStatistics.rovr += VAL16BIT;
171        if (car1 & CAR1_RFRG)
172            p_Dtsec->internalStatistics.rfrg += VAL16BIT;
173        if (car1 & CAR1_RJBR)
174            p_Dtsec->internalStatistics.rjbr += VAL16BIT;
175        if (car1 & CAR1_RDRP)
176            p_Dtsec->internalStatistics.rdrp += VAL16BIT;
177    }
178    if (car2)
179    {
180        if (car2  & CAR2_TFCS)
181            p_Dtsec->internalStatistics.tfcs += VAL12BIT;
182        if (car2  & CAR2_TBYT)
183            p_Dtsec->internalStatistics.tbyt += (uint64_t)VAL32BIT;
184        if (car2  & CAR2_TPKT)
185            p_Dtsec->internalStatistics.tpkt += VAL22BIT;
186        if (car2  & CAR2_TMCA)
187            p_Dtsec->internalStatistics.tmca += VAL22BIT;
188        if (car2  & CAR2_TBCA)
189            p_Dtsec->internalStatistics.tbca += VAL22BIT;
190        if (car2  & CAR2_TXPF)
191            p_Dtsec->internalStatistics.txpf += VAL16BIT;
192        if (car2  & CAR2_TDRP)
193            p_Dtsec->internalStatistics.tdrp += VAL16BIT;
194    }
195}
196
197/* .............................................................................. */
198
199static uint16_t DtsecGetMaxFrameLength(t_Handle h_Dtsec)
200{
201    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
202
203    SANITY_CHECK_RETURN_VALUE(p_Dtsec, E_INVALID_HANDLE, 0);
204    SANITY_CHECK_RETURN_VALUE(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE, 0);
205
206    return fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap);
207}
208
209/* .............................................................................. */
210
211static void DtsecIsr(t_Handle h_Dtsec)
212{
213    t_Dtsec             *p_Dtsec = (t_Dtsec *)h_Dtsec;
214    uint32_t            event;
215    struct dtsec_regs   *p_DtsecMemMap = p_Dtsec->p_MemMap;
216
217    /* do not handle MDIO events */
218    event = fman_dtsec_get_event(p_DtsecMemMap, (uint32_t)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN)));
219
220    event &= fman_dtsec_get_interrupt_mask(p_DtsecMemMap);
221
222    fman_dtsec_ack_event(p_DtsecMemMap, event);
223
224    if (event & DTSEC_IMASK_BREN)
225        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_RX);
226    if (event & DTSEC_IMASK_RXCEN)
227        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_CTL);
228    if (event & DTSEC_IMASK_MSROEN)
229        UpdateStatistics(p_Dtsec);
230    if (event & DTSEC_IMASK_GTSCEN)
231        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET);
232    if (event & DTSEC_IMASK_BTEN)
233        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_BAB_TX);
234    if (event & DTSEC_IMASK_TXCEN)
235        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_CTL);
236    if (event & DTSEC_IMASK_TXEEN)
237        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_ERR);
238    if (event & DTSEC_IMASK_LCEN)
239        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_LATE_COL);
240    if (event & DTSEC_IMASK_CRLEN)
241        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_COL_RET_LMT);
242    if (event & DTSEC_IMASK_XFUNEN)
243    {
244#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6
245        if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
246        {
247            uint32_t  tpkt1, tmpReg1, tpkt2, tmpReg2, i;
248            /* a. Write 0x00E0_0C00 to DTSEC_ID */
249            /* This is a read only regidter */
250
251            /* b. Read and save the value of TPKT */
252            tpkt1 = GET_UINT32(p_DtsecMemMap->tpkt);
253
254            /* c. Read the register at dTSEC address offset 0x32C */
255            tmpReg1 =  GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));
256
257            /* d. Compare bits [9:15] to bits [25:31] of the register at address offset 0x32C. */
258            if ((tmpReg1 & 0x007F0000) != (tmpReg1 & 0x0000007F))
259            {
260                /* If they are not equal, save the value of this register and wait for at least
261                 * MAXFRM*16 ns */
262                XX_UDelay((uint32_t)(MIN(DtsecGetMaxFrameLength(p_Dtsec)*16/1000, 1)));
263            }
264
265            /* e. Read and save TPKT again and read the register at dTSEC address offset
266                0x32C again*/
267            tpkt2 = GET_UINT32(p_DtsecMemMap->tpkt);
268            tmpReg2 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));
269
270            /* f. Compare the value of TPKT saved in step b to value read in step e. Also
271                compare bits [9:15] of the register at offset 0x32C saved in step d to the value
272                of bits [9:15] saved in step e. If the two registers values are unchanged, then
273                the transmit portion of the dTSEC controller is locked up and the user should
274                proceed to the recover sequence. */
275            if ((tpkt1 == tpkt2) && ((tmpReg1 & 0x007F0000) == (tmpReg2 & 0x007F0000)))
276            {
277                /* recover sequence */
278
279                /* a.Write a 1 to RCTRL[GRS]*/
280
281                WRITE_UINT32(p_DtsecMemMap->rctrl, GET_UINT32(p_DtsecMemMap->rctrl) | RCTRL_GRS);
282
283                /* b.Wait until IEVENT[GRSC]=1, or at least 100 us has elapsed. */
284                for (i = 0 ; i < 100 ; i++ )
285                {
286                    if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)
287                        break;
288                    XX_UDelay(1);
289                }
290                if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)
291                    WRITE_UINT32(p_DtsecMemMap->ievent, DTSEC_IMASK_GRSCEN);
292                else
293                    DBG(INFO,("Rx lockup due to dTSEC Tx lockup"));
294
295                /* c.Write a 1 to bit n of FM_RSTC (offset 0x0CC of FPM)*/
296                FmResetMac(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G, p_Dtsec->fmMacControllerDriver.macId);
297
298                /* d.Wait 4 Tx clocks (32 ns) */
299                XX_UDelay(1);
300
301                /* e.Write a 0 to bit n of FM_RSTC. */
302                /* cleared by FMAN */
303            }
304        }
305#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */
306
307        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_FIFO_UNDRN);
308    }
309    if (event & DTSEC_IMASK_MAGEN)
310        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_MAG_PCKT);
311    if (event & DTSEC_IMASK_GRSCEN)
312        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET);
313    if (event & DTSEC_IMASK_TDPEEN)
314        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_DATA_ERR);
315    if (event & DTSEC_IMASK_RDPEEN)
316        p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_RX_DATA_ERR);
317
318    /*  - masked interrupts */
319    ASSERT_COND(!(event & DTSEC_IMASK_ABRTEN));
320    ASSERT_COND(!(event & DTSEC_IMASK_IFERREN));
321}
322
323static void DtsecMdioIsr(t_Handle h_Dtsec)
324{
325    t_Dtsec             *p_Dtsec = (t_Dtsec *)h_Dtsec;
326    uint32_t            event;
327    struct dtsec_regs   *p_DtsecMemMap = p_Dtsec->p_MemMap;
328
329    event = GET_UINT32(p_DtsecMemMap->ievent);
330    /* handle only MDIO events */
331    event &= (DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN);
332    if (event)
333    {
334        event &= GET_UINT32(p_DtsecMemMap->imask);
335
336        WRITE_UINT32(p_DtsecMemMap->ievent, event);
337
338        if (event & DTSEC_IMASK_MMRDEN)
339            p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_RD_COMPLET);
340        if (event & DTSEC_IMASK_MMWREN)
341            p_Dtsec->f_Event(p_Dtsec->h_App, e_FM_MAC_EX_1G_MII_MNG_WR_COMPLET);
342    }
343}
344
345static void Dtsec1588Isr(t_Handle h_Dtsec)
346{
347    t_Dtsec             *p_Dtsec = (t_Dtsec *)h_Dtsec;
348    uint32_t            event;
349    struct dtsec_regs   *p_DtsecMemMap = p_Dtsec->p_MemMap;
350
351    if (p_Dtsec->ptpTsuEnabled)
352    {
353        event = fman_dtsec_check_and_clear_tmr_event(p_DtsecMemMap);
354
355        if (event)
356        {
357            ASSERT_COND(event & TMR_PEVENT_TSRE);
358            p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_1588_TS_RX_ERR);
359        }
360    }
361}
362
363/* ........................................................................... */
364
365static void FreeInitResources(t_Dtsec *p_Dtsec)
366{
367    if (p_Dtsec->mdioIrq != NO_IRQ)
368    {
369        XX_DisableIntr(p_Dtsec->mdioIrq);
370        XX_FreeIntr(p_Dtsec->mdioIrq);
371    }
372    FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_ERR);
373    FmUnregisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MOD_1G_MAC, p_Dtsec->macId, e_FM_INTR_TYPE_NORMAL);
374
375    /* release the driver's group hash table */
376    FreeHashTable(p_Dtsec->p_MulticastAddrHash);
377    p_Dtsec->p_MulticastAddrHash =   NULL;
378
379    /* release the driver's individual hash table */
380    FreeHashTable(p_Dtsec->p_UnicastAddrHash);
381    p_Dtsec->p_UnicastAddrHash =     NULL;
382}
383
384/* ........................................................................... */
385
386static t_Error GracefulStop(t_Dtsec *p_Dtsec, e_CommMode mode)
387{
388    struct dtsec_regs *p_MemMap;
389
390    ASSERT_COND(p_Dtsec);
391
392    p_MemMap = p_Dtsec->p_MemMap;
393    ASSERT_COND(p_MemMap);
394
395    /* Assert the graceful transmit stop bit */
396    if (mode & e_COMM_MODE_RX)
397    {
398        fman_dtsec_stop_rx(p_MemMap);
399
400#ifdef FM_GRS_ERRATA_DTSEC_A002
401        if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
402            XX_UDelay(100);
403#else  /* FM_GRS_ERRATA_DTSEC_A002 */
404#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
405        XX_UDelay(10);
406#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */
407#endif /* FM_GRS_ERRATA_DTSEC_A002 */
408    }
409
410    if (mode & e_COMM_MODE_TX)
411#if defined(FM_GTS_ERRATA_DTSEC_A004) || defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012)
412    if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
413        DBG(INFO, ("GTS not supported due to DTSEC_A004 errata."));
414#else  /* not defined(FM_GTS_ERRATA_DTSEC_A004) ||... */
415#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014
416        DBG(INFO, ("GTS not supported due to DTSEC_A0014 errata."));
417#else  /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
418        fman_dtsec_stop_tx(p_MemMap);
419#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
420#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||...  */
421
422    return E_OK;
423}
424
425/* .............................................................................. */
426
427static t_Error GracefulRestart(t_Dtsec *p_Dtsec, e_CommMode mode)
428{
429    struct dtsec_regs *p_MemMap;
430
431    ASSERT_COND(p_Dtsec);
432    p_MemMap = p_Dtsec->p_MemMap;
433    ASSERT_COND(p_MemMap);
434
435    /* clear the graceful receive stop bit */
436    if (mode & e_COMM_MODE_TX)
437        fman_dtsec_start_tx(p_MemMap);
438
439    if (mode & e_COMM_MODE_RX)
440        fman_dtsec_start_rx(p_MemMap);
441
442    return E_OK;
443}
444
445
446/*****************************************************************************/
447/*                      dTSEC Configs modification functions                 */
448/*****************************************************************************/
449
450/* .............................................................................. */
451
452static t_Error DtsecConfigLoopback(t_Handle h_Dtsec, bool newVal)
453{
454
455    t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
456
457    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
458    SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
459
460    p_Dtsec->p_DtsecDriverParam->loopback = newVal;
461
462    return E_OK;
463}
464
465/* .............................................................................. */
466
467static t_Error DtsecConfigMaxFrameLength(t_Handle h_Dtsec, uint16_t newVal)
468{
469    t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
470
471    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
472    SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
473
474    p_Dtsec->p_DtsecDriverParam->maximum_frame = newVal;
475
476    return E_OK;
477}
478
479/* .............................................................................. */
480
481static t_Error DtsecConfigPadAndCrc(t_Handle h_Dtsec, bool newVal)
482{
483    t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
484
485    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
486    SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
487
488    p_Dtsec->p_DtsecDriverParam->tx_pad_crc = newVal;
489
490    return E_OK;
491}
492
493/* .............................................................................. */
494
495static t_Error DtsecConfigHalfDuplex(t_Handle h_Dtsec, bool newVal)
496{
497    t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
498
499    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
500    SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
501
502    p_Dtsec->p_DtsecDriverParam->halfdup_on = newVal;
503
504    return E_OK;
505}
506
507/* .............................................................................. */
508
509static t_Error DtsecConfigTbiPhyAddr(t_Handle h_Dtsec, uint8_t newVal)
510{
511    t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
512
513    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
514    SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
515
516    p_Dtsec->p_DtsecDriverParam->tbi_phy_addr = newVal;
517
518    return E_OK;
519}
520
521/* .............................................................................. */
522
523static t_Error DtsecConfigLengthCheck(t_Handle h_Dtsec, bool newVal)
524{
525    t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
526
527    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
528    SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
529
530    p_Dtsec->p_DtsecDriverParam->rx_len_check = newVal;
531
532    return E_OK;
533}
534
535/* .............................................................................. */
536
537static t_Error DtsecConfigException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)
538{
539    t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
540    uint32_t    bitMask = 0;
541
542    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
543    SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
544
545    if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)
546    {
547        GET_EXCEPTION_FLAG(bitMask, exception);
548        if (bitMask)
549        {
550            if (enable)
551                p_Dtsec->exceptions |= bitMask;
552            else
553                p_Dtsec->exceptions &= ~bitMask;
554        }
555        else
556            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
557    }
558    else
559    {
560        if (!p_Dtsec->ptpTsuEnabled)
561            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));
562
563        if (enable)
564            p_Dtsec->enTsuErrExeption = TRUE;
565        else
566            p_Dtsec->enTsuErrExeption = FALSE;
567    }
568
569    return E_OK;
570}
571
572
573/*****************************************************************************/
574/*                      dTSEC Run Time API functions                         */
575/*****************************************************************************/
576
577/* .............................................................................. */
578
579static t_Error DtsecEnable(t_Handle h_Dtsec,  e_CommMode mode)
580{
581    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
582
583    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
584    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
585
586    fman_dtsec_enable(p_Dtsec->p_MemMap,
587                 (bool)!!(mode & e_COMM_MODE_RX),
588                 (bool)!!(mode & e_COMM_MODE_TX));
589
590    GracefulRestart(p_Dtsec, mode);
591
592    return E_OK;
593}
594
595/* .............................................................................. */
596
597static t_Error DtsecDisable (t_Handle h_Dtsec, e_CommMode mode)
598{
599    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
600
601    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
602    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
603
604    GracefulStop(p_Dtsec, mode);
605
606    fman_dtsec_disable(p_Dtsec->p_MemMap,
607                  (bool)!!(mode & e_COMM_MODE_RX),
608                  (bool)!!(mode & e_COMM_MODE_TX));
609
610    return E_OK;
611}
612
613/* .............................................................................. */
614
615static t_Error DtsecSetTxPauseFrames(t_Handle h_Dtsec,
616                                     uint8_t  priority,
617                                     uint16_t pauseTime,
618                                     uint16_t threshTime)
619{
620    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
621
622    UNUSED(priority);UNUSED(threshTime);
623
624    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
625    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
626
627#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003
628    if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
629        if (0 < pauseTime && pauseTime <= 320)
630            RETURN_ERROR(MINOR, E_INVALID_VALUE,
631                     ("This pause-time value of %d is illegal due to errata dTSEC-A003!"
632                      " value should be greater than 320."));
633#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */
634
635    fman_dtsec_set_tx_pause_frames(p_Dtsec->p_MemMap, pauseTime);
636    return E_OK;
637}
638
639/* .............................................................................. */
640/* backward compatibility. will be removed in the future. */
641static t_Error DtsecTxMacPause(t_Handle h_Dtsec, uint16_t pauseTime)
642{
643    return DtsecSetTxPauseFrames(h_Dtsec, 0, pauseTime, 0);
644}
645
646/* .............................................................................. */
647
648static t_Error DtsecRxIgnoreMacPause(t_Handle h_Dtsec, bool en)
649{
650    t_Dtsec         *p_Dtsec = (t_Dtsec *)h_Dtsec;
651    bool            accept_pause = !en;
652
653    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
654    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
655
656    fman_dtsec_handle_rx_pause(p_Dtsec->p_MemMap, accept_pause);
657
658    return E_OK;
659}
660
661/* .............................................................................. */
662
663static t_Error DtsecEnable1588TimeStamp(t_Handle h_Dtsec)
664{
665    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
666
667    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
668    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
669
670    p_Dtsec->ptpTsuEnabled = TRUE;
671    fman_dtsec_set_ts(p_Dtsec->p_MemMap, TRUE);
672
673    return E_OK;
674}
675
676/* .............................................................................. */
677
678static t_Error DtsecDisable1588TimeStamp(t_Handle h_Dtsec)
679{
680    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
681
682    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
683    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
684
685    p_Dtsec->ptpTsuEnabled = FALSE;
686    fman_dtsec_set_ts(p_Dtsec->p_MemMap, FALSE);
687
688    return E_OK;
689}
690
691/* .............................................................................. */
692
693static t_Error DtsecGetStatistics(t_Handle h_Dtsec, t_FmMacStatistics *p_Statistics)
694{
695    t_Dtsec             *p_Dtsec = (t_Dtsec *)h_Dtsec;
696    struct dtsec_regs   *p_DtsecMemMap;
697
698    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
699    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
700    SANITY_CHECK_RETURN_ERROR(p_Statistics, E_NULL_POINTER);
701
702    p_DtsecMemMap = p_Dtsec->p_MemMap;
703
704    if (p_Dtsec->statisticsLevel == e_FM_MAC_NONE_STATISTICS)
705        RETURN_ERROR(MINOR, E_INVALID_STATE, ("Statistics disabled"));
706
707    memset(p_Statistics, 0xff, sizeof(t_FmMacStatistics));
708
709    if (p_Dtsec->statisticsLevel == e_FM_MAC_FULL_STATISTICS)
710    {
711        p_Statistics->eStatPkts64 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR64)
712                + p_Dtsec->internalStatistics.tr64;
713        p_Statistics->eStatPkts65to127 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR127)
714                + p_Dtsec->internalStatistics.tr127;
715        p_Statistics->eStatPkts128to255 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR255)
716                + p_Dtsec->internalStatistics.tr255;
717        p_Statistics->eStatPkts256to511 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR511)
718                + p_Dtsec->internalStatistics.tr511;
719        p_Statistics->eStatPkts512to1023 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TR1K)
720                + p_Dtsec->internalStatistics.tr1k;
721        p_Statistics->eStatPkts1024to1518 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMAX)
722                + p_Dtsec->internalStatistics.trmax;
723        p_Statistics->eStatPkts1519to1522 = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TRMGV)
724                + p_Dtsec->internalStatistics.trmgv;
725
726        /* MIB II */
727        p_Statistics->ifInOctets = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBYT)
728                + p_Dtsec->internalStatistics.rbyt;
729        p_Statistics->ifInPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RPKT)
730                + p_Dtsec->internalStatistics.rpkt;
731        p_Statistics->ifInUcastPkts = 0;
732        p_Statistics->ifInMcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RMCA)
733                + p_Dtsec->internalStatistics.rmca;
734        p_Statistics->ifInBcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RBCA)
735                + p_Dtsec->internalStatistics.rbca;
736        p_Statistics->ifOutOctets = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBYT)
737                + p_Dtsec->internalStatistics.tbyt;
738        p_Statistics->ifOutPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TPKT)
739                + p_Dtsec->internalStatistics.tpkt;
740        p_Statistics->ifOutUcastPkts = 0;
741        p_Statistics->ifOutMcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TMCA)
742                + p_Dtsec->internalStatistics.tmca;
743        p_Statistics->ifOutBcastPkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TBCA)
744                + p_Dtsec->internalStatistics.tbca;
745    }
746
747    p_Statistics->eStatFragments = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RFRG)
748            + p_Dtsec->internalStatistics.rfrg;
749    p_Statistics->eStatJabbers = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RJBR)
750            + p_Dtsec->internalStatistics.rjbr;
751    p_Statistics->eStatsDropEvents = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RDRP)
752            + p_Dtsec->internalStatistics.rdrp;
753    p_Statistics->eStatCRCAlignErrors = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RALN)
754            + p_Dtsec->internalStatistics.raln;
755    p_Statistics->eStatUndersizePkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RUND)
756            + p_Dtsec->internalStatistics.rund;
757    p_Statistics->eStatOversizePkts = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_ROVR)
758            + p_Dtsec->internalStatistics.rovr;
759    p_Statistics->reStatPause = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_RXPF)
760            + p_Dtsec->internalStatistics.rxpf;
761    p_Statistics->teStatPause = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TXPF)
762            + p_Dtsec->internalStatistics.txpf;
763    p_Statistics->ifInDiscards = p_Statistics->eStatsDropEvents;
764    p_Statistics->ifInErrors = p_Statistics->eStatsDropEvents + p_Statistics->eStatCRCAlignErrors
765            + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RFLR) + p_Dtsec->internalStatistics.rflr
766            + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCDE) + p_Dtsec->internalStatistics.rcde
767            + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_RCSE) + p_Dtsec->internalStatistics.rcse;
768
769    p_Statistics->ifOutDiscards = fman_dtsec_get_stat_counter(p_DtsecMemMap, E_DTSEC_STAT_TDRP)
770            + p_Dtsec->internalStatistics.tdrp;
771    p_Statistics->ifOutErrors = p_Statistics->ifOutDiscards                                           /**< Number of frames transmitted with error: */
772            + fman_dtsec_get_stat_counter(p_DtsecMemMap,E_DTSEC_STAT_TFCS)
773            + p_Dtsec->internalStatistics.tfcs;
774
775    return E_OK;
776}
777
778/* .............................................................................. */
779
780static t_Error DtsecModifyMacAddress (t_Handle h_Dtsec, t_EnetAddr *p_EnetAddr)
781{
782    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
783
784    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
785    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
786
787    /* Initialize MAC Station Address registers (1 & 2)    */
788    /* Station address have to be swapped (big endian to little endian */
789    p_Dtsec->addr = ENET_ADDR_TO_UINT64(*p_EnetAddr);
790    fman_dtsec_set_mac_address(p_Dtsec->p_MemMap, (uint8_t *)(*p_EnetAddr));
791
792    return E_OK;
793}
794
795/* .............................................................................. */
796
797static t_Error DtsecResetCounters (t_Handle h_Dtsec)
798{
799    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
800
801    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
802    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
803
804    /* clear HW counters */
805    fman_dtsec_reset_stat(p_Dtsec->p_MemMap);
806
807    /* clear SW counters holding carries */
808    memset(&p_Dtsec->internalStatistics, 0, sizeof(t_InternalStatistics));
809
810    return E_OK;
811}
812
813/* .............................................................................. */
814
815static t_Error DtsecAddExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
816{
817    t_Dtsec   *p_Dtsec = (t_Dtsec *) h_Dtsec;
818    uint64_t  ethAddr;
819    uint8_t   paddrNum;
820
821    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
822    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
823
824    ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
825
826    if (ethAddr & GROUP_ADDRESS)
827        /* Multicast address has no effect in PADDR */
828        RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));
829
830    /* Make sure no PADDR contains this address */
831    for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
832        if (p_Dtsec->indAddrRegUsed[paddrNum])
833            if (p_Dtsec->paddr[paddrNum] == ethAddr)
834                RETURN_ERROR(MAJOR, E_ALREADY_EXISTS, NO_MSG);
835
836    /* Find first unused PADDR */
837    for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
838        if (!(p_Dtsec->indAddrRegUsed[paddrNum]))
839        {
840            /* mark this PADDR as used */
841            p_Dtsec->indAddrRegUsed[paddrNum] = TRUE;
842            /* store address */
843            p_Dtsec->paddr[paddrNum] = ethAddr;
844
845            /* put in hardware */
846            fman_dtsec_add_addr_in_paddr(p_Dtsec->p_MemMap, (uint64_t)PTR_TO_UINT(&ethAddr), paddrNum);
847            p_Dtsec->numOfIndAddrInRegs++;
848
849            return E_OK;
850        }
851
852    /* No free PADDR */
853    RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
854}
855
856/* .............................................................................. */
857
858static t_Error DtsecDelExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
859{
860    t_Dtsec   *p_Dtsec = (t_Dtsec *) h_Dtsec;
861    uint64_t  ethAddr;
862    uint8_t   paddrNum;
863
864    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
865    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
866
867    ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
868
869    /* Find used PADDR containing this address */
870    for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
871    {
872        if ((p_Dtsec->indAddrRegUsed[paddrNum]) &&
873            (p_Dtsec->paddr[paddrNum] == ethAddr))
874        {
875            /* mark this PADDR as not used */
876            p_Dtsec->indAddrRegUsed[paddrNum] = FALSE;
877            /* clear in hardware */
878            fman_dtsec_clear_addr_in_paddr(p_Dtsec->p_MemMap, paddrNum);
879            p_Dtsec->numOfIndAddrInRegs--;
880
881            return E_OK;
882        }
883    }
884
885    RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
886}
887
888/* .............................................................................. */
889
890static t_Error DtsecAddHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
891{
892    t_Dtsec         *p_Dtsec = (t_Dtsec *)h_Dtsec;
893    t_EthHashEntry  *p_HashEntry;
894    uint64_t        ethAddr;
895    int32_t         bucket;
896    uint32_t        crc;
897    bool            mcast, ghtx;
898
899    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
900    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
901
902    ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
903
904    ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);
905    mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);
906
907    if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */
908        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket"));
909
910    crc = GetMacAddrHashCode(ethAddr);
911
912    /* considering the 9 highest order bits in crc H[8:0]:
913     * if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register
914     * and H[5:1] (next 5 bits) identify the hash bit
915     * if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register
916     * and H[4:0] (next 5 bits) identify the hash bit.
917     *
918     * In bucket index output the low 5 bits identify the hash register bit,
919     * while the higher 4 bits identify the hash register
920     */
921
922    if (ghtx)
923        bucket = (int32_t)((crc >> 23) & 0x1ff);
924    else {
925        bucket = (int32_t)((crc >> 24) & 0xff);
926        /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
927        if (mcast)
928            bucket += 0x100;
929    }
930
931    fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, TRUE);
932
933    /* Create element to be added to the driver hash table */
934    p_HashEntry = (t_EthHashEntry *)XX_Malloc(sizeof(t_EthHashEntry));
935    p_HashEntry->addr = ethAddr;
936    INIT_LIST(&p_HashEntry->node);
937
938    if (ethAddr & MAC_GROUP_ADDRESS)
939        /* Group Address */
940        NCSW_LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]));
941    else
942        NCSW_LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]));
943
944    return E_OK;
945}
946
947/* .............................................................................. */
948
949static t_Error DtsecDelHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
950{
951    t_Dtsec         *p_Dtsec = (t_Dtsec *)h_Dtsec;
952    t_List          *p_Pos;
953    t_EthHashEntry  *p_HashEntry = NULL;
954    uint64_t        ethAddr;
955    int32_t         bucket;
956    uint32_t        crc;
957    bool            mcast, ghtx;
958
959    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
960    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
961
962    ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
963
964    ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);
965    mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);
966
967    if (ghtx && !mcast) /* Cannot handle unicast mac addr when GHTX is on */
968        RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Could not compute hash bucket"));
969
970    crc = GetMacAddrHashCode(ethAddr);
971
972    if (ghtx)
973        bucket = (int32_t)((crc >> 23) & 0x1ff);
974    else {
975        bucket = (int32_t)((crc >> 24) & 0xff);
976        /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
977        if (mcast)
978            bucket += 0x100;
979    }
980
981    if (ethAddr & MAC_GROUP_ADDRESS)
982    {
983        /* Group Address */
984        NCSW_LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))
985        {
986            p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
987            if (p_HashEntry->addr == ethAddr)
988            {
989                NCSW_LIST_DelAndInit(&p_HashEntry->node);
990                XX_Free(p_HashEntry);
991                break;
992            }
993        }
994        if (NCSW_LIST_IsEmpty(&p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))
995            fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);
996    }
997    else
998    {
999        /* Individual Address */
1000        NCSW_LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))
1001        {
1002            p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
1003            if (p_HashEntry->addr == ethAddr)
1004            {
1005                NCSW_LIST_DelAndInit(&p_HashEntry->node);
1006                XX_Free(p_HashEntry);
1007                break;
1008            }
1009        }
1010        if (NCSW_LIST_IsEmpty(&p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))
1011            fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);
1012    }
1013
1014    /* address does not exist */
1015    ASSERT_COND(p_HashEntry != NULL);
1016
1017    return E_OK;
1018}
1019
1020/* .............................................................................. */
1021
1022static t_Error DtsecSetPromiscuous(t_Handle h_Dtsec, bool newVal)
1023{
1024    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
1025
1026    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1027    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1028
1029    fman_dtsec_set_uc_promisc(p_Dtsec->p_MemMap, newVal);
1030    fman_dtsec_set_mc_promisc(p_Dtsec->p_MemMap, newVal);
1031
1032    return E_OK;
1033}
1034
1035/* .............................................................................. */
1036
1037static t_Error DtsecSetStatistics(t_Handle h_Dtsec, e_FmMacStatisticsLevel statisticsLevel)
1038{
1039    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
1040    t_Error     err;
1041
1042    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1043    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1044
1045    p_Dtsec->statisticsLevel = statisticsLevel;
1046
1047    err = (t_Error)fman_dtsec_set_stat_level(p_Dtsec->p_MemMap,
1048                                        (enum dtsec_stat_level)statisticsLevel);
1049    if (err != E_OK)
1050        return err;
1051
1052    switch (statisticsLevel)
1053    {
1054    case (e_FM_MAC_NONE_STATISTICS):
1055            p_Dtsec->exceptions &= ~DTSEC_IMASK_MSROEN;
1056            break;
1057    case (e_FM_MAC_PARTIAL_STATISTICS):
1058            p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;
1059            break;
1060    case (e_FM_MAC_FULL_STATISTICS):
1061            p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;
1062            break;
1063        default:
1064            RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);
1065    }
1066
1067    return E_OK;
1068}
1069
1070/* .............................................................................. */
1071
1072static t_Error DtsecSetWakeOnLan(t_Handle h_Dtsec, bool en)
1073{
1074    t_Dtsec         *p_Dtsec = (t_Dtsec *)h_Dtsec;
1075
1076    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
1077    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1078
1079    fman_dtsec_set_wol(p_Dtsec->p_MemMap, en);
1080
1081    return E_OK;
1082}
1083
1084/* .............................................................................. */
1085
1086static t_Error DtsecAdjustLink(t_Handle h_Dtsec, e_EnetSpeed speed, bool fullDuplex)
1087{
1088    t_Dtsec             *p_Dtsec = (t_Dtsec *)h_Dtsec;
1089    int                 err;
1090    enum enet_interface enet_interface;
1091    enum enet_speed     enet_speed;
1092
1093    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1094    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1095
1096    p_Dtsec->enetMode = MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode), speed);
1097    enet_interface = (enum enet_interface) ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode);
1098    enet_speed = (enum enet_speed) ENET_SPEED_FROM_MODE(p_Dtsec->enetMode);
1099    p_Dtsec->halfDuplex = !fullDuplex;
1100
1101    err = fman_dtsec_adjust_link(p_Dtsec->p_MemMap, enet_interface, enet_speed, fullDuplex);
1102
1103    if (err == -EINVAL)
1104        RETURN_ERROR(MAJOR, E_CONFLICT, ("Ethernet interface does not support Half Duplex mode"));
1105
1106    return (t_Error)err;
1107}
1108
1109/* .............................................................................. */
1110
1111static t_Error DtsecRestartAutoneg(t_Handle h_Dtsec)
1112{
1113    t_Dtsec      *p_Dtsec = (t_Dtsec *)h_Dtsec;
1114    uint16_t     tmpReg16;
1115
1116    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1117    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1118
1119    DTSEC_MII_ReadPhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, &tmpReg16);
1120
1121    tmpReg16 &= ~( PHY_CR_SPEED0 | PHY_CR_SPEED1 );
1122    tmpReg16 |= (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
1123
1124    DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, tmpReg16);
1125
1126    return E_OK;
1127}
1128
1129/* .............................................................................. */
1130
1131static t_Error DtsecGetId(t_Handle h_Dtsec, uint32_t *macId)
1132{
1133    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
1134
1135    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1136    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1137
1138    *macId = p_Dtsec->macId;
1139
1140    return E_OK;
1141}
1142
1143/* .............................................................................. */
1144
1145static t_Error DtsecGetVersion(t_Handle h_Dtsec, uint32_t *macVersion)
1146{
1147    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
1148
1149    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1150    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1151
1152    *macVersion = fman_dtsec_get_revision(p_Dtsec->p_MemMap);
1153
1154    return E_OK;
1155}
1156
1157/* .............................................................................. */
1158
1159static t_Error DtsecSetException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)
1160{
1161    t_Dtsec     *p_Dtsec = (t_Dtsec *)h_Dtsec;
1162    uint32_t    bitMask = 0;
1163
1164    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1165    SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1166
1167    if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)
1168    {
1169        GET_EXCEPTION_FLAG(bitMask, exception);
1170        if (bitMask)
1171        {
1172            if (enable)
1173                p_Dtsec->exceptions |= bitMask;
1174            else
1175                p_Dtsec->exceptions &= ~bitMask;
1176        }
1177        else
1178            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
1179
1180        if (enable)
1181            fman_dtsec_enable_interrupt(p_Dtsec->p_MemMap, bitMask);
1182        else
1183            fman_dtsec_disable_interrupt(p_Dtsec->p_MemMap, bitMask);
1184    }
1185    else
1186    {
1187        if (!p_Dtsec->ptpTsuEnabled)
1188            RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));
1189
1190        if (enable)
1191        {
1192            p_Dtsec->enTsuErrExeption = TRUE;
1193            fman_dtsec_enable_tmr_interrupt(p_Dtsec->p_MemMap);
1194        }
1195        else
1196        {
1197            p_Dtsec->enTsuErrExeption = FALSE;
1198            fman_dtsec_disable_tmr_interrupt(p_Dtsec->p_MemMap);
1199        }
1200    }
1201
1202    return E_OK;
1203}
1204
1205
1206/*****************************************************************************/
1207/*                      dTSEC Init & Free API                                   */
1208/*****************************************************************************/
1209
1210/* .............................................................................. */
1211
1212static t_Error DtsecInit(t_Handle h_Dtsec)
1213{
1214    t_Dtsec             *p_Dtsec = (t_Dtsec *)h_Dtsec;
1215    struct dtsec_cfg    *p_DtsecDriverParam;
1216    t_Error             err;
1217    uint16_t            maxFrmLn;
1218    enum enet_interface enet_interface;
1219    enum enet_speed     enet_speed;
1220    t_EnetAddr          ethAddr;
1221
1222    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1223    SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1224    SANITY_CHECK_RETURN_ERROR(p_Dtsec->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE);
1225
1226    FM_GetRevision(p_Dtsec->fmMacControllerDriver.h_Fm, &p_Dtsec->fmMacControllerDriver.fmRevInfo);
1227    CHECK_INIT_PARAMETERS(p_Dtsec, CheckInitParameters);
1228
1229    p_DtsecDriverParam  = p_Dtsec->p_DtsecDriverParam;
1230    p_Dtsec->halfDuplex = p_DtsecDriverParam->halfdup_on;
1231
1232    enet_interface = (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode);
1233    enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_Dtsec->enetMode);
1234    MAKE_ENET_ADDR_FROM_UINT64(p_Dtsec->addr, ethAddr);
1235
1236    err = (t_Error)fman_dtsec_init(p_Dtsec->p_MemMap,
1237                              p_DtsecDriverParam,
1238                              enet_interface,
1239                              enet_speed,
1240                              (uint8_t*)ethAddr,
1241                              p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev,
1242                              p_Dtsec->fmMacControllerDriver.fmRevInfo.minorRev,
1243                              p_Dtsec->exceptions);
1244    if (err)
1245    {
1246        FreeInitResources(p_Dtsec);
1247        RETURN_ERROR(MAJOR, err, ("This DTSEC version does not support the required i/f mode"));
1248    }
1249
1250    if (ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode) == e_ENET_IF_SGMII)
1251    {
1252        uint16_t            tmpReg16;
1253
1254        /* Configure the TBI PHY Control Register */
1255        tmpReg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET;
1256        DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);
1257
1258        tmpReg16 = PHY_TBICON_CLK_SEL;
1259        DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);
1260
1261        tmpReg16 = (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
1262        DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);
1263
1264        if (p_Dtsec->enetMode & ENET_IF_SGMII_BASEX)
1265            tmpReg16 = PHY_TBIANA_1000X;
1266        else
1267            tmpReg16 = PHY_TBIANA_SGMII;
1268        DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 4, tmpReg16);
1269
1270        tmpReg16 = (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
1271
1272        DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);
1273    }
1274
1275    /* Max Frame Length */
1276    maxFrmLn = fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap);
1277    err = FmSetMacMaxFrame(p_Dtsec->fmMacControllerDriver.h_Fm, e_FM_MAC_1G,
1278            p_Dtsec->fmMacControllerDriver.macId, maxFrmLn);
1279    if (err)
1280        RETURN_ERROR(MINOR,err, NO_MSG);
1281
1282    p_Dtsec->p_MulticastAddrHash = AllocHashTable(EXTENDED_HASH_TABLE_SIZE);
1283    if (!p_Dtsec->p_MulticastAddrHash) {
1284        FreeInitResources(p_Dtsec);
1285        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MC hash table is FAILED"));
1286    }
1287
1288    p_Dtsec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
1289    if (!p_Dtsec->p_UnicastAddrHash)
1290    {
1291        FreeInitResources(p_Dtsec);
1292        RETURN_ERROR(MAJOR, E_NO_MEMORY, ("UC hash table is FAILED"));
1293    }
1294
1295    /* register err intr handler for dtsec to FPM (err)*/
1296    FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,
1297                   e_FM_MOD_1G_MAC,
1298                   p_Dtsec->macId,
1299                   e_FM_INTR_TYPE_ERR,
1300                   DtsecIsr,
1301                   p_Dtsec);
1302    /* register 1588 intr handler for TMR to FPM (normal)*/
1303    FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,
1304                   e_FM_MOD_1G_MAC,
1305                   p_Dtsec->macId,
1306                   e_FM_INTR_TYPE_NORMAL,
1307                   Dtsec1588Isr,
1308                   p_Dtsec);
1309    /* register normal intr handler for dtsec to main interrupt controller. */
1310    if (p_Dtsec->mdioIrq != NO_IRQ)
1311    {
1312        XX_SetIntr(p_Dtsec->mdioIrq, DtsecMdioIsr, p_Dtsec);
1313        XX_EnableIntr(p_Dtsec->mdioIrq);
1314    }
1315
1316    XX_Free(p_DtsecDriverParam);
1317    p_Dtsec->p_DtsecDriverParam = NULL;
1318
1319    err = DtsecSetStatistics(h_Dtsec, e_FM_MAC_FULL_STATISTICS);
1320    if (err)
1321    {
1322        FreeInitResources(p_Dtsec);
1323        RETURN_ERROR(MAJOR, err, ("Undefined statistics level"));
1324    }
1325
1326    return E_OK;
1327}
1328
1329/* ........................................................................... */
1330
1331static t_Error DtsecFree(t_Handle h_Dtsec)
1332{
1333    t_Dtsec      *p_Dtsec = (t_Dtsec *)h_Dtsec;
1334
1335    SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1336
1337    if (p_Dtsec->p_DtsecDriverParam)
1338    {
1339        /* Called after config */
1340        XX_Free(p_Dtsec->p_DtsecDriverParam);
1341        p_Dtsec->p_DtsecDriverParam = NULL;
1342    }
1343    else
1344        /* Called after init */
1345        FreeInitResources(p_Dtsec);
1346
1347    XX_Free(p_Dtsec);
1348
1349    return E_OK;
1350}
1351
1352/* .............................................................................. */
1353
1354static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
1355{
1356    p_FmMacControllerDriver->f_FM_MAC_Init                      = DtsecInit;
1357    p_FmMacControllerDriver->f_FM_MAC_Free                      = DtsecFree;
1358
1359    p_FmMacControllerDriver->f_FM_MAC_SetStatistics             = DtsecSetStatistics;
1360    p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback            = DtsecConfigLoopback;
1361    p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength      = DtsecConfigMaxFrameLength;
1362
1363    p_FmMacControllerDriver->f_FM_MAC_ConfigWan                 = NULL; /* Not supported on dTSEC */
1364
1365    p_FmMacControllerDriver->f_FM_MAC_ConfigPadAndCrc           = DtsecConfigPadAndCrc;
1366    p_FmMacControllerDriver->f_FM_MAC_ConfigHalfDuplex          = DtsecConfigHalfDuplex;
1367    p_FmMacControllerDriver->f_FM_MAC_ConfigLengthCheck         = DtsecConfigLengthCheck;
1368    p_FmMacControllerDriver->f_FM_MAC_ConfigTbiPhyAddr          = DtsecConfigTbiPhyAddr;
1369    p_FmMacControllerDriver->f_FM_MAC_ConfigException           = DtsecConfigException;
1370    p_FmMacControllerDriver->f_FM_MAC_ConfigResetOnInit         = NULL;
1371
1372    p_FmMacControllerDriver->f_FM_MAC_Enable                    = DtsecEnable;
1373    p_FmMacControllerDriver->f_FM_MAC_Disable                   = DtsecDisable;
1374    p_FmMacControllerDriver->f_FM_MAC_Resume                    = NULL;
1375
1376    p_FmMacControllerDriver->f_FM_MAC_SetException              = DtsecSetException;
1377
1378    p_FmMacControllerDriver->f_FM_MAC_SetPromiscuous            = DtsecSetPromiscuous;
1379    p_FmMacControllerDriver->f_FM_MAC_AdjustLink                = DtsecAdjustLink;
1380    p_FmMacControllerDriver->f_FM_MAC_SetWakeOnLan              = DtsecSetWakeOnLan;
1381    p_FmMacControllerDriver->f_FM_MAC_RestartAutoneg            = DtsecRestartAutoneg;
1382
1383    p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp       = DtsecEnable1588TimeStamp;
1384    p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp      = DtsecDisable1588TimeStamp;
1385
1386    p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames      = DtsecTxMacPause;
1387    p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames          = DtsecSetTxPauseFrames;
1388    p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames    = DtsecRxIgnoreMacPause;
1389
1390    p_FmMacControllerDriver->f_FM_MAC_ResetCounters             = DtsecResetCounters;
1391    p_FmMacControllerDriver->f_FM_MAC_GetStatistics             = DtsecGetStatistics;
1392
1393    p_FmMacControllerDriver->f_FM_MAC_ModifyMacAddr             = DtsecModifyMacAddress;
1394    p_FmMacControllerDriver->f_FM_MAC_AddHashMacAddr            = DtsecAddHashMacAddress;
1395    p_FmMacControllerDriver->f_FM_MAC_RemoveHashMacAddr         = DtsecDelHashMacAddress;
1396    p_FmMacControllerDriver->f_FM_MAC_AddExactMatchMacAddr      = DtsecAddExactMatchMacAddress;
1397    p_FmMacControllerDriver->f_FM_MAC_RemovelExactMatchMacAddr  = DtsecDelExactMatchMacAddress;
1398    p_FmMacControllerDriver->f_FM_MAC_GetId                     = DtsecGetId;
1399    p_FmMacControllerDriver->f_FM_MAC_GetVersion                = DtsecGetVersion;
1400    p_FmMacControllerDriver->f_FM_MAC_GetMaxFrameLength         = DtsecGetMaxFrameLength;
1401
1402    p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg           = DTSEC_MII_WritePhyReg;
1403    p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg            = DTSEC_MII_ReadPhyReg;
1404
1405}
1406
1407
1408/*****************************************************************************/
1409/*                      dTSEC Config Main Entry                             */
1410/*****************************************************************************/
1411
1412/* .............................................................................. */
1413
1414t_Handle  DTSEC_Config(t_FmMacParams *p_FmMacParam)
1415{
1416    t_Dtsec             *p_Dtsec;
1417    struct dtsec_cfg    *p_DtsecDriverParam;
1418    uintptr_t           baseAddr;
1419
1420    SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
1421
1422    baseAddr = p_FmMacParam->baseAddr;
1423
1424    /* allocate memory for the UCC GETH data structure. */
1425    p_Dtsec = (t_Dtsec *)XX_Malloc(sizeof(t_Dtsec));
1426    if (!p_Dtsec)
1427    {
1428        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver structure"));
1429        return NULL;
1430    }
1431    memset(p_Dtsec, 0, sizeof(t_Dtsec));
1432    InitFmMacControllerDriver(&p_Dtsec->fmMacControllerDriver);
1433
1434    /* allocate memory for the dTSEC driver parameters data structure. */
1435    p_DtsecDriverParam = (struct dtsec_cfg *) XX_Malloc(sizeof(struct dtsec_cfg));
1436    if (!p_DtsecDriverParam)
1437    {
1438        XX_Free(p_Dtsec);
1439        REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver parameters"));
1440        return NULL;
1441    }
1442    memset(p_DtsecDriverParam, 0, sizeof(struct dtsec_cfg));
1443
1444    /* Plant parameter structure pointer */
1445    p_Dtsec->p_DtsecDriverParam = p_DtsecDriverParam;
1446
1447    fman_dtsec_defconfig(p_DtsecDriverParam);
1448
1449    p_Dtsec->p_MemMap           = (struct dtsec_regs *)UINT_TO_PTR(baseAddr);
1450    p_Dtsec->p_MiiMemMap        = (struct dtsec_mii_reg *)UINT_TO_PTR(baseAddr + DTSEC_TO_MII_OFFSET);
1451    p_Dtsec->addr               = ENET_ADDR_TO_UINT64(p_FmMacParam->addr);
1452    p_Dtsec->enetMode           = p_FmMacParam->enetMode;
1453    p_Dtsec->macId              = p_FmMacParam->macId;
1454    p_Dtsec->exceptions         = DEFAULT_exceptions;
1455    p_Dtsec->mdioIrq            = p_FmMacParam->mdioIrq;
1456    p_Dtsec->f_Exception        = p_FmMacParam->f_Exception;
1457    p_Dtsec->f_Event            = p_FmMacParam->f_Event;
1458    p_Dtsec->h_App              = p_FmMacParam->h_App;
1459    p_Dtsec->ptpTsuEnabled      = p_Dtsec->p_DtsecDriverParam->ptp_tsu_en;
1460    p_Dtsec->enTsuErrExeption   = p_Dtsec->p_DtsecDriverParam->ptp_exception_en;
1461    p_Dtsec->tbi_phy_addr       = p_Dtsec->p_DtsecDriverParam->tbi_phy_addr;
1462
1463    return p_Dtsec;
1464}
1465