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(ðAddr), 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