xref: /freebsd/sys/contrib/ncsw/Peripherals/FM/MAC/dtsec.c (revision c2c014f24c10f90d85126ac5fbd4d8524de32b1c)
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 
CheckInitParameters(t_Dtsec * p_Dtsec)56 static 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 
GetMacAddrHashCode(uint64_t ethAddr)113 static 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 
UpdateStatistics(t_Dtsec * p_Dtsec)127 static 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 
DtsecGetMaxFrameLength(t_Handle h_Dtsec)199 static 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 
DtsecIsr(t_Handle h_Dtsec)211 static 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 
DtsecMdioIsr(t_Handle h_Dtsec)323 static 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 
Dtsec1588Isr(t_Handle h_Dtsec)345 static 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 
FreeInitResources(t_Dtsec * p_Dtsec)365 static 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 
GracefulStop(t_Dtsec * p_Dtsec,e_CommMode mode)386 static 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 
GracefulRestart(t_Dtsec * p_Dtsec,e_CommMode mode)427 static 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 
DtsecConfigLoopback(t_Handle h_Dtsec,bool newVal)452 static 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 
DtsecConfigMaxFrameLength(t_Handle h_Dtsec,uint16_t newVal)467 static 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 
DtsecConfigPadAndCrc(t_Handle h_Dtsec,bool newVal)481 static 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 
DtsecConfigHalfDuplex(t_Handle h_Dtsec,bool newVal)495 static 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 
DtsecConfigTbiPhyAddr(t_Handle h_Dtsec,uint8_t newVal)509 static 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 
DtsecConfigLengthCheck(t_Handle h_Dtsec,bool newVal)523 static 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 
DtsecConfigException(t_Handle h_Dtsec,e_FmMacExceptions exception,bool enable)537 static 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 
DtsecEnable(t_Handle h_Dtsec,e_CommMode mode)579 static 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 
DtsecDisable(t_Handle h_Dtsec,e_CommMode mode)597 static 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 
DtsecSetTxPauseFrames(t_Handle h_Dtsec,uint8_t priority,uint16_t pauseTime,uint16_t threshTime)615 static 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. */
DtsecTxMacPause(t_Handle h_Dtsec,uint16_t pauseTime)641 static t_Error DtsecTxMacPause(t_Handle h_Dtsec, uint16_t pauseTime)
642 {
643     return DtsecSetTxPauseFrames(h_Dtsec, 0, pauseTime, 0);
644 }
645 
646 /* .............................................................................. */
647 
DtsecRxIgnoreMacPause(t_Handle h_Dtsec,bool en)648 static 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 
DtsecEnable1588TimeStamp(t_Handle h_Dtsec)663 static 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 
DtsecDisable1588TimeStamp(t_Handle h_Dtsec)678 static 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 
DtsecGetStatistics(t_Handle h_Dtsec,t_FmMacStatistics * p_Statistics)693 static 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 
DtsecModifyMacAddress(t_Handle h_Dtsec,t_EnetAddr * p_EnetAddr)780 static 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 
DtsecResetCounters(t_Handle h_Dtsec)797 static 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 
DtsecAddExactMatchMacAddress(t_Handle h_Dtsec,t_EnetAddr * p_EthAddr)815 static 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 
DtsecDelExactMatchMacAddress(t_Handle h_Dtsec,t_EnetAddr * p_EthAddr)858 static 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 
DtsecAddHashMacAddress(t_Handle h_Dtsec,t_EnetAddr * p_EthAddr)890 static 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 
DtsecDelHashMacAddress(t_Handle h_Dtsec,t_EnetAddr * p_EthAddr)949 static 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 
DtsecSetPromiscuous(t_Handle h_Dtsec,bool newVal)1022 static 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 
DtsecSetStatistics(t_Handle h_Dtsec,e_FmMacStatisticsLevel statisticsLevel)1037 static 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 
DtsecSetWakeOnLan(t_Handle h_Dtsec,bool en)1072 static 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 
DtsecAdjustLink(t_Handle h_Dtsec,e_EnetSpeed speed,bool fullDuplex)1086 static 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 
DtsecRestartAutoneg(t_Handle h_Dtsec)1111 static 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 
DtsecGetId(t_Handle h_Dtsec,uint32_t * macId)1131 static 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 
DtsecGetVersion(t_Handle h_Dtsec,uint32_t * macVersion)1145 static 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 
DtsecSetException(t_Handle h_Dtsec,e_FmMacExceptions exception,bool enable)1159 static 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 
DtsecInit(t_Handle h_Dtsec)1212 static 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 
DtsecFree(t_Handle h_Dtsec)1331 static 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 
InitFmMacControllerDriver(t_FmMacControllerDriver * p_FmMacControllerDriver)1354 static 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 
DTSEC_Config(t_FmMacParams * p_FmMacParam)1414 t_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