2 * Copyright 2008-2013 Freescale Semiconductor Inc.
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.
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
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.
33 /******************************************************************************
36 @Description FMan dTSEC driver
37 *//***************************************************************************/
40 #include "error_ext.h"
41 #include "string_ext.h"
43 #include "endian_ext.h"
44 #include "debug_ext.h"
45 #include "crc_mac_addr_ext.h"
47 #include "fm_common.h"
49 #include "fsl_fman_dtsec.h"
50 #include "fsl_fman_dtsec_mii_acc.h"
52 /*****************************************************************************/
53 /* Internal routines */
54 /*****************************************************************************/
56 static t_Error CheckInitParameters(t_Dtsec *p_Dtsec)
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 ));
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"));
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 */
111 /* ......................................................................... */
113 static uint32_t GetMacAddrHashCode(uint64_t ethAddr)
117 /* CRC calculation */
118 GET_MAC_ADDR_CRC(ethAddr, crc);
120 crc = GetMirror32(crc);
125 /* ......................................................................... */
127 static void UpdateStatistics(t_Dtsec *p_Dtsec)
131 fman_dtsec_get_clear_carry_regs(p_Dtsec->p_MemMap, &car1, &car2);
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;
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;
197 /* .............................................................................. */
199 static uint16_t DtsecGetMaxFrameLength(t_Handle h_Dtsec)
201 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
203 SANITY_CHECK_RETURN_VALUE(p_Dtsec, E_INVALID_HANDLE, 0);
204 SANITY_CHECK_RETURN_VALUE(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE, 0);
206 return fman_dtsec_get_max_frame_len(p_Dtsec->p_MemMap);
209 /* .............................................................................. */
211 static void DtsecIsr(t_Handle h_Dtsec)
213 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
215 struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
217 /* do not handle MDIO events */
218 event = fman_dtsec_get_event(p_DtsecMemMap, (uint32_t)(~(DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN)));
220 event &= fman_dtsec_get_interrupt_mask(p_DtsecMemMap);
222 fman_dtsec_ack_event(p_DtsecMemMap, event);
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)
244 #ifdef FM_TX_LOCKUP_ERRATA_DTSEC6
245 if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
247 uint32_t tpkt1, tmpReg1, tpkt2, tmpReg2, i;
248 /* a. Write 0x00E0_0C00 to DTSEC_ID */
249 /* This is a read only regidter */
251 /* b. Read and save the value of TPKT */
252 tpkt1 = GET_UINT32(p_DtsecMemMap->tpkt);
254 /* c. Read the register at dTSEC address offset 0x32C */
255 tmpReg1 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));
257 /* d. Compare bits [9:15] to bits [25:31] of the register at address offset 0x32C. */
258 if ((tmpReg1 & 0x007F0000) != (tmpReg1 & 0x0000007F))
260 /* If they are not equal, save the value of this register and wait for at least
262 XX_UDelay((uint32_t)(MIN(DtsecGetMaxFrameLength(p_Dtsec)*16/1000, 1)));
265 /* e. Read and save TPKT again and read the register at dTSEC address offset
267 tpkt2 = GET_UINT32(p_DtsecMemMap->tpkt);
268 tmpReg2 = GET_UINT32(*(uint32_t*)((uint8_t*)p_DtsecMemMap + 0x32c));
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)))
277 /* recover sequence */
279 /* a.Write a 1 to RCTRL[GRS]*/
281 WRITE_UINT32(p_DtsecMemMap->rctrl, GET_UINT32(p_DtsecMemMap->rctrl) | RCTRL_GRS);
283 /* b.Wait until IEVENT[GRSC]=1, or at least 100 us has elapsed. */
284 for (i = 0 ; i < 100 ; i++ )
286 if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)
290 if (GET_UINT32(p_DtsecMemMap->ievent) & DTSEC_IMASK_GRSCEN)
291 WRITE_UINT32(p_DtsecMemMap->ievent, DTSEC_IMASK_GRSCEN);
293 DBG(INFO,("Rx lockup due to dTSEC Tx lockup"));
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);
298 /* d.Wait 4 Tx clocks (32 ns) */
301 /* e.Write a 0 to bit n of FM_RSTC. */
302 /* cleared by FMAN */
305 #endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */
307 p_Dtsec->f_Exception(p_Dtsec->h_App, e_FM_MAC_EX_1G_TX_FIFO_UNDRN);
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);
318 /* - masked interrupts */
319 ASSERT_COND(!(event & DTSEC_IMASK_ABRTEN));
320 ASSERT_COND(!(event & DTSEC_IMASK_IFERREN));
323 static void DtsecMdioIsr(t_Handle h_Dtsec)
325 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
327 struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
329 event = GET_UINT32(p_DtsecMemMap->ievent);
330 /* handle only MDIO events */
331 event &= (DTSEC_IMASK_MMRDEN | DTSEC_IMASK_MMWREN);
334 event &= GET_UINT32(p_DtsecMemMap->imask);
336 WRITE_UINT32(p_DtsecMemMap->ievent, event);
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);
345 static void Dtsec1588Isr(t_Handle h_Dtsec)
347 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
349 struct dtsec_regs *p_DtsecMemMap = p_Dtsec->p_MemMap;
351 if (p_Dtsec->ptpTsuEnabled)
353 event = fman_dtsec_check_and_clear_tmr_event(p_DtsecMemMap);
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);
363 /* ........................................................................... */
365 static void FreeInitResources(t_Dtsec *p_Dtsec)
367 if (p_Dtsec->mdioIrq != NO_IRQ)
369 XX_DisableIntr(p_Dtsec->mdioIrq);
370 XX_FreeIntr(p_Dtsec->mdioIrq);
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);
375 /* release the driver's group hash table */
376 FreeHashTable(p_Dtsec->p_MulticastAddrHash);
377 p_Dtsec->p_MulticastAddrHash = NULL;
379 /* release the driver's individual hash table */
380 FreeHashTable(p_Dtsec->p_UnicastAddrHash);
381 p_Dtsec->p_UnicastAddrHash = NULL;
384 /* ........................................................................... */
386 static t_Error GracefulStop(t_Dtsec *p_Dtsec, e_CommMode mode)
388 struct dtsec_regs *p_MemMap;
390 ASSERT_COND(p_Dtsec);
392 p_MemMap = p_Dtsec->p_MemMap;
393 ASSERT_COND(p_MemMap);
395 /* Assert the graceful transmit stop bit */
396 if (mode & e_COMM_MODE_RX)
398 fman_dtsec_stop_rx(p_MemMap);
400 #ifdef FM_GRS_ERRATA_DTSEC_A002
401 if (p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev == 2)
403 #else /* FM_GRS_ERRATA_DTSEC_A002 */
404 #ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
406 #endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */
407 #endif /* FM_GRS_ERRATA_DTSEC_A002 */
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) ||... */
425 /* .............................................................................. */
427 static t_Error GracefulRestart(t_Dtsec *p_Dtsec, e_CommMode mode)
429 struct dtsec_regs *p_MemMap;
431 ASSERT_COND(p_Dtsec);
432 p_MemMap = p_Dtsec->p_MemMap;
433 ASSERT_COND(p_MemMap);
435 /* clear the graceful receive stop bit */
436 if (mode & e_COMM_MODE_TX)
437 fman_dtsec_start_tx(p_MemMap);
439 if (mode & e_COMM_MODE_RX)
440 fman_dtsec_start_rx(p_MemMap);
446 /*****************************************************************************/
447 /* dTSEC Configs modification functions */
448 /*****************************************************************************/
450 /* .............................................................................. */
452 static t_Error DtsecConfigLoopback(t_Handle h_Dtsec, bool newVal)
455 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
457 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
458 SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
460 p_Dtsec->p_DtsecDriverParam->loopback = newVal;
465 /* .............................................................................. */
467 static t_Error DtsecConfigMaxFrameLength(t_Handle h_Dtsec, uint16_t newVal)
469 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
471 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
472 SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
474 p_Dtsec->p_DtsecDriverParam->maximum_frame = newVal;
479 /* .............................................................................. */
481 static t_Error DtsecConfigPadAndCrc(t_Handle h_Dtsec, bool newVal)
483 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
485 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
486 SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
488 p_Dtsec->p_DtsecDriverParam->tx_pad_crc = newVal;
493 /* .............................................................................. */
495 static t_Error DtsecConfigHalfDuplex(t_Handle h_Dtsec, bool newVal)
497 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
499 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
500 SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
502 p_Dtsec->p_DtsecDriverParam->halfdup_on = newVal;
507 /* .............................................................................. */
509 static t_Error DtsecConfigTbiPhyAddr(t_Handle h_Dtsec, uint8_t newVal)
511 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
513 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
514 SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
516 p_Dtsec->p_DtsecDriverParam->tbi_phy_addr = newVal;
521 /* .............................................................................. */
523 static t_Error DtsecConfigLengthCheck(t_Handle h_Dtsec, bool newVal)
525 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
527 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
528 SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
530 p_Dtsec->p_DtsecDriverParam->rx_len_check = newVal;
535 /* .............................................................................. */
537 static t_Error DtsecConfigException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)
539 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
540 uint32_t bitMask = 0;
542 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
543 SANITY_CHECK_RETURN_ERROR(p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
545 if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)
547 GET_EXCEPTION_FLAG(bitMask, exception);
551 p_Dtsec->exceptions |= bitMask;
553 p_Dtsec->exceptions &= ~bitMask;
556 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
560 if (!p_Dtsec->ptpTsuEnabled)
561 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));
564 p_Dtsec->enTsuErrExeption = TRUE;
566 p_Dtsec->enTsuErrExeption = FALSE;
573 /*****************************************************************************/
574 /* dTSEC Run Time API functions */
575 /*****************************************************************************/
577 /* .............................................................................. */
579 static t_Error DtsecEnable(t_Handle h_Dtsec, e_CommMode mode)
581 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
583 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
584 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
586 fman_dtsec_enable(p_Dtsec->p_MemMap,
587 (bool)!!(mode & e_COMM_MODE_RX),
588 (bool)!!(mode & e_COMM_MODE_TX));
590 GracefulRestart(p_Dtsec, mode);
595 /* .............................................................................. */
597 static t_Error DtsecDisable (t_Handle h_Dtsec, e_CommMode mode)
599 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
601 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
602 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
604 GracefulStop(p_Dtsec, mode);
606 fman_dtsec_disable(p_Dtsec->p_MemMap,
607 (bool)!!(mode & e_COMM_MODE_RX),
608 (bool)!!(mode & e_COMM_MODE_TX));
613 /* .............................................................................. */
615 static t_Error DtsecSetTxPauseFrames(t_Handle h_Dtsec,
620 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
622 UNUSED(priority);UNUSED(threshTime);
624 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
625 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
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 */
635 fman_dtsec_set_tx_pause_frames(p_Dtsec->p_MemMap, pauseTime);
639 /* .............................................................................. */
640 /* backward compatibility. will be removed in the future. */
641 static t_Error DtsecTxMacPause(t_Handle h_Dtsec, uint16_t pauseTime)
643 return DtsecSetTxPauseFrames(h_Dtsec, 0, pauseTime, 0);
646 /* .............................................................................. */
648 static t_Error DtsecRxIgnoreMacPause(t_Handle h_Dtsec, bool en)
650 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
651 bool accept_pause = !en;
653 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
654 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
656 fman_dtsec_handle_rx_pause(p_Dtsec->p_MemMap, accept_pause);
661 /* .............................................................................. */
663 static t_Error DtsecEnable1588TimeStamp(t_Handle h_Dtsec)
665 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
667 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
668 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
670 p_Dtsec->ptpTsuEnabled = TRUE;
671 fman_dtsec_set_ts(p_Dtsec->p_MemMap, TRUE);
676 /* .............................................................................. */
678 static t_Error DtsecDisable1588TimeStamp(t_Handle h_Dtsec)
680 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
682 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
683 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
685 p_Dtsec->ptpTsuEnabled = FALSE;
686 fman_dtsec_set_ts(p_Dtsec->p_MemMap, FALSE);
691 /* .............................................................................. */
693 static t_Error DtsecGetStatistics(t_Handle h_Dtsec, t_FmMacStatistics *p_Statistics)
695 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
696 struct dtsec_regs *p_DtsecMemMap;
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);
702 p_DtsecMemMap = p_Dtsec->p_MemMap;
704 if (p_Dtsec->statisticsLevel == e_FM_MAC_NONE_STATISTICS)
705 RETURN_ERROR(MINOR, E_INVALID_STATE, ("Statistics disabled"));
707 memset(p_Statistics, 0xff, sizeof(t_FmMacStatistics));
709 if (p_Dtsec->statisticsLevel == e_FM_MAC_FULL_STATISTICS)
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;
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;
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;
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;
778 /* .............................................................................. */
780 static t_Error DtsecModifyMacAddress (t_Handle h_Dtsec, t_EnetAddr *p_EnetAddr)
782 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
784 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
785 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
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));
795 /* .............................................................................. */
797 static t_Error DtsecResetCounters (t_Handle h_Dtsec)
799 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
801 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
802 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
804 /* clear HW counters */
805 fman_dtsec_reset_stat(p_Dtsec->p_MemMap);
807 /* clear SW counters holding carries */
808 memset(&p_Dtsec->internalStatistics, 0, sizeof(t_InternalStatistics));
813 /* .............................................................................. */
815 static t_Error DtsecAddExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
817 t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec;
821 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
822 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
824 ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
826 if (ethAddr & GROUP_ADDRESS)
827 /* Multicast address has no effect in PADDR */
828 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Multicast address"));
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);
836 /* Find first unused PADDR */
837 for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
838 if (!(p_Dtsec->indAddrRegUsed[paddrNum]))
840 /* mark this PADDR as used */
841 p_Dtsec->indAddrRegUsed[paddrNum] = TRUE;
843 p_Dtsec->paddr[paddrNum] = ethAddr;
845 /* put in hardware */
846 fman_dtsec_add_addr_in_paddr(p_Dtsec->p_MemMap, (uint64_t)PTR_TO_UINT(ðAddr), paddrNum);
847 p_Dtsec->numOfIndAddrInRegs++;
853 RETURN_ERROR(MAJOR, E_FULL, NO_MSG);
856 /* .............................................................................. */
858 static t_Error DtsecDelExactMatchMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
860 t_Dtsec *p_Dtsec = (t_Dtsec *) h_Dtsec;
864 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
865 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
867 ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
869 /* Find used PADDR containing this address */
870 for (paddrNum = 0; paddrNum < DTSEC_NUM_OF_PADDRS; paddrNum++)
872 if ((p_Dtsec->indAddrRegUsed[paddrNum]) &&
873 (p_Dtsec->paddr[paddrNum] == ethAddr))
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--;
885 RETURN_ERROR(MAJOR, E_NOT_FOUND, NO_MSG);
888 /* .............................................................................. */
890 static t_Error DtsecAddHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
892 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
893 t_EthHashEntry *p_HashEntry;
899 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
900 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
902 ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
904 ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);
905 mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);
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"));
910 crc = GetMacAddrHashCode(ethAddr);
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.
918 * In bucket index output the low 5 bits identify the hash register bit,
919 * while the higher 4 bits identify the hash register
923 bucket = (int32_t)((crc >> 23) & 0x1ff);
925 bucket = (int32_t)((crc >> 24) & 0xff);
926 /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
931 fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, TRUE);
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);
938 if (ethAddr & MAC_GROUP_ADDRESS)
940 NCSW_LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]));
942 NCSW_LIST_AddToTail(&(p_HashEntry->node), &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]));
947 /* .............................................................................. */
949 static t_Error DtsecDelHashMacAddress(t_Handle h_Dtsec, t_EnetAddr *p_EthAddr)
951 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
953 t_EthHashEntry *p_HashEntry = NULL;
959 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
960 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
962 ethAddr = ENET_ADDR_TO_UINT64(*p_EthAddr);
964 ghtx = (bool)((fman_dtsec_get_rctrl(p_Dtsec->p_MemMap) & RCTRL_GHTX) ? TRUE : FALSE);
965 mcast = (bool)((ethAddr & MAC_GROUP_ADDRESS) ? TRUE : FALSE);
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"));
970 crc = GetMacAddrHashCode(ethAddr);
973 bucket = (int32_t)((crc >> 23) & 0x1ff);
975 bucket = (int32_t)((crc >> 24) & 0xff);
976 /* if !ghtx and mcast the bit must be set in gaddr instead of igaddr. */
981 if (ethAddr & MAC_GROUP_ADDRESS)
984 NCSW_LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))
986 p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
987 if (p_HashEntry->addr == ethAddr)
989 NCSW_LIST_DelAndInit(&p_HashEntry->node);
990 XX_Free(p_HashEntry);
994 if (NCSW_LIST_IsEmpty(&p_Dtsec->p_MulticastAddrHash->p_Lsts[bucket]))
995 fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);
999 /* Individual Address */
1000 NCSW_LIST_FOR_EACH(p_Pos, &(p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))
1002 p_HashEntry = ETH_HASH_ENTRY_OBJ(p_Pos);
1003 if (p_HashEntry->addr == ethAddr)
1005 NCSW_LIST_DelAndInit(&p_HashEntry->node);
1006 XX_Free(p_HashEntry);
1010 if (NCSW_LIST_IsEmpty(&p_Dtsec->p_UnicastAddrHash->p_Lsts[bucket]))
1011 fman_dtsec_set_bucket(p_Dtsec->p_MemMap, bucket, FALSE);
1014 /* address does not exist */
1015 ASSERT_COND(p_HashEntry != NULL);
1020 /* .............................................................................. */
1022 static t_Error DtsecSetPromiscuous(t_Handle h_Dtsec, bool newVal)
1024 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1026 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1027 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1029 fman_dtsec_set_uc_promisc(p_Dtsec->p_MemMap, newVal);
1030 fman_dtsec_set_mc_promisc(p_Dtsec->p_MemMap, newVal);
1035 /* .............................................................................. */
1037 static t_Error DtsecSetStatistics(t_Handle h_Dtsec, e_FmMacStatisticsLevel statisticsLevel)
1039 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1042 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1043 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1045 p_Dtsec->statisticsLevel = statisticsLevel;
1047 err = (t_Error)fman_dtsec_set_stat_level(p_Dtsec->p_MemMap,
1048 (enum dtsec_stat_level)statisticsLevel);
1052 switch (statisticsLevel)
1054 case (e_FM_MAC_NONE_STATISTICS):
1055 p_Dtsec->exceptions &= ~DTSEC_IMASK_MSROEN;
1057 case (e_FM_MAC_PARTIAL_STATISTICS):
1058 p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;
1060 case (e_FM_MAC_FULL_STATISTICS):
1061 p_Dtsec->exceptions |= DTSEC_IMASK_MSROEN;
1064 RETURN_ERROR(MINOR, E_INVALID_SELECTION, NO_MSG);
1070 /* .............................................................................. */
1072 static t_Error DtsecSetWakeOnLan(t_Handle h_Dtsec, bool en)
1074 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1076 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_STATE);
1077 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1079 fman_dtsec_set_wol(p_Dtsec->p_MemMap, en);
1084 /* .............................................................................. */
1086 static t_Error DtsecAdjustLink(t_Handle h_Dtsec, e_EnetSpeed speed, bool fullDuplex)
1088 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1090 enum enet_interface enet_interface;
1091 enum enet_speed enet_speed;
1093 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1094 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
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;
1101 err = fman_dtsec_adjust_link(p_Dtsec->p_MemMap, enet_interface, enet_speed, fullDuplex);
1104 RETURN_ERROR(MAJOR, E_CONFLICT, ("Ethernet interface does not support Half Duplex mode"));
1106 return (t_Error)err;
1109 /* .............................................................................. */
1111 static t_Error DtsecRestartAutoneg(t_Handle h_Dtsec)
1113 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1116 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1117 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1119 DTSEC_MII_ReadPhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, &tmpReg16);
1121 tmpReg16 &= ~( PHY_CR_SPEED0 | PHY_CR_SPEED1 );
1122 tmpReg16 |= (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
1124 DTSEC_MII_WritePhyReg(p_Dtsec, p_Dtsec->tbi_phy_addr, 0, tmpReg16);
1129 /* .............................................................................. */
1131 static t_Error DtsecGetId(t_Handle h_Dtsec, uint32_t *macId)
1133 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1135 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1136 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1138 *macId = p_Dtsec->macId;
1143 /* .............................................................................. */
1145 static t_Error DtsecGetVersion(t_Handle h_Dtsec, uint32_t *macVersion)
1147 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1149 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1150 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1152 *macVersion = fman_dtsec_get_revision(p_Dtsec->p_MemMap);
1157 /* .............................................................................. */
1159 static t_Error DtsecSetException(t_Handle h_Dtsec, e_FmMacExceptions exception, bool enable)
1161 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1162 uint32_t bitMask = 0;
1164 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1165 SANITY_CHECK_RETURN_ERROR(!p_Dtsec->p_DtsecDriverParam, E_INVALID_STATE);
1167 if (exception != e_FM_MAC_EX_1G_1588_TS_RX_ERR)
1169 GET_EXCEPTION_FLAG(bitMask, exception);
1173 p_Dtsec->exceptions |= bitMask;
1175 p_Dtsec->exceptions &= ~bitMask;
1178 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception"));
1181 fman_dtsec_enable_interrupt(p_Dtsec->p_MemMap, bitMask);
1183 fman_dtsec_disable_interrupt(p_Dtsec->p_MemMap, bitMask);
1187 if (!p_Dtsec->ptpTsuEnabled)
1188 RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exception valid for 1588 only"));
1192 p_Dtsec->enTsuErrExeption = TRUE;
1193 fman_dtsec_enable_tmr_interrupt(p_Dtsec->p_MemMap);
1197 p_Dtsec->enTsuErrExeption = FALSE;
1198 fman_dtsec_disable_tmr_interrupt(p_Dtsec->p_MemMap);
1206 /*****************************************************************************/
1207 /* dTSEC Init & Free API */
1208 /*****************************************************************************/
1210 /* .............................................................................. */
1212 static t_Error DtsecInit(t_Handle h_Dtsec)
1214 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1215 struct dtsec_cfg *p_DtsecDriverParam;
1218 enum enet_interface enet_interface;
1219 enum enet_speed enet_speed;
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);
1226 FM_GetRevision(p_Dtsec->fmMacControllerDriver.h_Fm, &p_Dtsec->fmMacControllerDriver.fmRevInfo);
1227 CHECK_INIT_PARAMETERS(p_Dtsec, CheckInitParameters);
1229 p_DtsecDriverParam = p_Dtsec->p_DtsecDriverParam;
1230 p_Dtsec->halfDuplex = p_DtsecDriverParam->halfdup_on;
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);
1236 err = (t_Error)fman_dtsec_init(p_Dtsec->p_MemMap,
1241 p_Dtsec->fmMacControllerDriver.fmRevInfo.majorRev,
1242 p_Dtsec->fmMacControllerDriver.fmRevInfo.minorRev,
1243 p_Dtsec->exceptions);
1246 FreeInitResources(p_Dtsec);
1247 RETURN_ERROR(MAJOR, err, ("This DTSEC version does not support the required i/f mode"));
1250 if (ENET_INTERFACE_FROM_MODE(p_Dtsec->enetMode) == e_ENET_IF_SGMII)
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);
1258 tmpReg16 = PHY_TBICON_CLK_SEL;
1259 DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 17, tmpReg16);
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);
1264 if (p_Dtsec->enetMode & ENET_IF_SGMII_BASEX)
1265 tmpReg16 = PHY_TBIANA_1000X;
1267 tmpReg16 = PHY_TBIANA_SGMII;
1268 DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 4, tmpReg16);
1270 tmpReg16 = (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
1272 DTSEC_MII_WritePhyReg(p_Dtsec, (uint8_t)p_DtsecDriverParam->tbipa, 0, tmpReg16);
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);
1280 RETURN_ERROR(MINOR,err, NO_MSG);
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"));
1288 p_Dtsec->p_UnicastAddrHash = AllocHashTable(HASH_TABLE_SIZE);
1289 if (!p_Dtsec->p_UnicastAddrHash)
1291 FreeInitResources(p_Dtsec);
1292 RETURN_ERROR(MAJOR, E_NO_MEMORY, ("UC hash table is FAILED"));
1295 /* register err intr handler for dtsec to FPM (err)*/
1296 FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,
1302 /* register 1588 intr handler for TMR to FPM (normal)*/
1303 FmRegisterIntr(p_Dtsec->fmMacControllerDriver.h_Fm,
1306 e_FM_INTR_TYPE_NORMAL,
1309 /* register normal intr handler for dtsec to main interrupt controller. */
1310 if (p_Dtsec->mdioIrq != NO_IRQ)
1312 XX_SetIntr(p_Dtsec->mdioIrq, DtsecMdioIsr, p_Dtsec);
1313 XX_EnableIntr(p_Dtsec->mdioIrq);
1316 XX_Free(p_DtsecDriverParam);
1317 p_Dtsec->p_DtsecDriverParam = NULL;
1319 err = DtsecSetStatistics(h_Dtsec, e_FM_MAC_FULL_STATISTICS);
1322 FreeInitResources(p_Dtsec);
1323 RETURN_ERROR(MAJOR, err, ("Undefined statistics level"));
1329 /* ........................................................................... */
1331 static t_Error DtsecFree(t_Handle h_Dtsec)
1333 t_Dtsec *p_Dtsec = (t_Dtsec *)h_Dtsec;
1335 SANITY_CHECK_RETURN_ERROR(p_Dtsec, E_INVALID_HANDLE);
1337 if (p_Dtsec->p_DtsecDriverParam)
1339 /* Called after config */
1340 XX_Free(p_Dtsec->p_DtsecDriverParam);
1341 p_Dtsec->p_DtsecDriverParam = NULL;
1344 /* Called after init */
1345 FreeInitResources(p_Dtsec);
1352 /* .............................................................................. */
1354 static void InitFmMacControllerDriver(t_FmMacControllerDriver *p_FmMacControllerDriver)
1356 p_FmMacControllerDriver->f_FM_MAC_Init = DtsecInit;
1357 p_FmMacControllerDriver->f_FM_MAC_Free = DtsecFree;
1359 p_FmMacControllerDriver->f_FM_MAC_SetStatistics = DtsecSetStatistics;
1360 p_FmMacControllerDriver->f_FM_MAC_ConfigLoopback = DtsecConfigLoopback;
1361 p_FmMacControllerDriver->f_FM_MAC_ConfigMaxFrameLength = DtsecConfigMaxFrameLength;
1363 p_FmMacControllerDriver->f_FM_MAC_ConfigWan = NULL; /* Not supported on dTSEC */
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;
1372 p_FmMacControllerDriver->f_FM_MAC_Enable = DtsecEnable;
1373 p_FmMacControllerDriver->f_FM_MAC_Disable = DtsecDisable;
1374 p_FmMacControllerDriver->f_FM_MAC_Resume = NULL;
1376 p_FmMacControllerDriver->f_FM_MAC_SetException = DtsecSetException;
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;
1383 p_FmMacControllerDriver->f_FM_MAC_Enable1588TimeStamp = DtsecEnable1588TimeStamp;
1384 p_FmMacControllerDriver->f_FM_MAC_Disable1588TimeStamp = DtsecDisable1588TimeStamp;
1386 p_FmMacControllerDriver->f_FM_MAC_SetTxAutoPauseFrames = DtsecTxMacPause;
1387 p_FmMacControllerDriver->f_FM_MAC_SetTxPauseFrames = DtsecSetTxPauseFrames;
1388 p_FmMacControllerDriver->f_FM_MAC_SetRxIgnorePauseFrames = DtsecRxIgnoreMacPause;
1390 p_FmMacControllerDriver->f_FM_MAC_ResetCounters = DtsecResetCounters;
1391 p_FmMacControllerDriver->f_FM_MAC_GetStatistics = DtsecGetStatistics;
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;
1402 p_FmMacControllerDriver->f_FM_MAC_MII_WritePhyReg = DTSEC_MII_WritePhyReg;
1403 p_FmMacControllerDriver->f_FM_MAC_MII_ReadPhyReg = DTSEC_MII_ReadPhyReg;
1408 /*****************************************************************************/
1409 /* dTSEC Config Main Entry */
1410 /*****************************************************************************/
1412 /* .............................................................................. */
1414 t_Handle DTSEC_Config(t_FmMacParams *p_FmMacParam)
1417 struct dtsec_cfg *p_DtsecDriverParam;
1420 SANITY_CHECK_RETURN_VALUE(p_FmMacParam, E_NULL_POINTER, NULL);
1422 baseAddr = p_FmMacParam->baseAddr;
1424 /* allocate memory for the UCC GETH data structure. */
1425 p_Dtsec = (t_Dtsec *)XX_Malloc(sizeof(t_Dtsec));
1428 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver structure"));
1431 memset(p_Dtsec, 0, sizeof(t_Dtsec));
1432 InitFmMacControllerDriver(&p_Dtsec->fmMacControllerDriver);
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)
1439 REPORT_ERROR(MAJOR, E_NO_MEMORY, ("dTSEC driver parameters"));
1442 memset(p_DtsecDriverParam, 0, sizeof(struct dtsec_cfg));
1444 /* Plant parameter structure pointer */
1445 p_Dtsec->p_DtsecDriverParam = p_DtsecDriverParam;
1447 fman_dtsec_defconfig(p_DtsecDriverParam);
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;